Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

Commit

Permalink
Fixing bug on protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
vilanovi committed Apr 18, 2014
1 parent 4fd160d commit c025711
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 19 deletions.
1 change: 0 additions & 1 deletion NSObject+Motis.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@

@end


/*
* MOTIS AUTOMATIC VALIDATION
*
Expand Down
68 changes: 53 additions & 15 deletions NSObject+Motis.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ - (id)initWithKeyPath:(NSString*)keyPath

@end

#pragma mark -
// ------------------------------------------------------------------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------------------------------------------ //

@interface NSObject (Motis_Private)

/** ---------------------------------------------- **
Expand Down Expand Up @@ -114,12 +119,12 @@ - (NSString*)mts_typeAttributeForKey:(NSString*)key;
- (BOOL)mts_isClassTypeTypeAttribute:(NSString*)typeAttribute;

/**
* Returns the class object for the given attribute type or nil if cannot be created.
* Retrieve the class name and the array of protocols that the property implements.
* @param className The returning class name.
* @param protocols The returning array of protocols.
* @param typeAttribute The value returned by `-mts_typeAttributeForKey:`.
* @return The related class object.
*/
- (Class)mts_classForTypeAttribute:(NSString*)typeAttribute;

- (void)mts_getClassName:(out NSString *__autoreleasing*)className protocols:(out NSArray *__autoreleasing*)protocols fromTypeAttribute:(NSString*)typeAttribute;

/** ---------------------------------------------- **
* @name Automatic Validation
Expand Down Expand Up @@ -567,15 +572,28 @@ - (BOOL)mts_isClassTypeTypeAttribute:(NSString*)typeAttribute
return [typeAttribute hasPrefix:@"T@"] && ([typeAttribute length] > 1);
}

- (Class)mts_classForTypeAttribute:(NSString*)typeAttribute
- (void)mts_getClassName:(out NSString *__autoreleasing*)className protocols:(out NSArray *__autoreleasing*)protocols fromTypeAttribute:(NSString*)typeAttribute
{
if ([self mts_isClassTypeTypeAttribute:typeAttribute])
{
NSString *typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)];
return NSClassFromString(typeClassName);
typeAttribute = [typeAttribute substringWithRange:NSMakeRange(3, typeAttribute.length-4)];

NSString *protocolNames = nil;

NSScanner *scanner = [NSScanner scannerWithString:typeAttribute];
[scanner scanUpToString:@"<" intoString:className];
[scanner scanUpToString:@">" intoString:&protocolNames];

if (*className == nil)
*className = @"";

if (protocolNames.length > 0)
{
protocolNames = [protocolNames substringFromIndex:1];
protocolNames = [protocolNames stringByReplacingOccurrencesOfString:@" " withString:@""];
*protocols = [protocolNames componentsSeparatedByString:@","];
}
}

return nil;
}

- (BOOL)mts_validateAutomaticallyValue:(inout __autoreleasing id *)ioValue forKey:(NSString*)key
Expand All @@ -593,15 +611,35 @@ - (BOOL)mts_validateAutomaticallyValue:(inout __autoreleasing id *)ioValue forKe

if ([self mts_isClassTypeTypeAttribute:typeAttribute])
{
if (strcmp(rawPropertyType, @encode(id)) == 0)
return YES;
NSString *className = nil;
NSArray *protocols = nil;

Class typeClass = [self mts_classForTypeAttribute:typeAttribute];
[self mts_getClassName:&className protocols:&protocols fromTypeAttribute:typeAttribute];

if (typeClass != nil)
if (className.length == 0)
{
MJLog(@"%@ --> %@", key, NSStringFromClass(typeClass));
return [self mts_validateAutomaticallyValue:ioValue toClass:typeClass forKey:key];
// It's an "id".

// Actually, we should make a compare like this:
// if (strcmp(rawPropertyType, @encode(id)) == 0)
// return YES;
//
// However, becuase of the "if" statements, we know that our typeAttribute begins with a "@" and
// if "className.length" == 0 means that the "rawPropertyType" to be compared is exactly an @encode(id).
//
// Therefore, we return directly YES.

return YES;
}
else
{
Class typeClass = NSClassFromString(className);

if (typeClass)
{
MJLog(@"%@ --> %@", key, NSStringFromClass(typeClass));
return [self mts_validateAutomaticallyValue:ioValue toClass:typeClass forKey:key];
}
}

return NO;
Expand Down
3 changes: 3 additions & 0 deletions SampleProject/Motis Tests/MJTestObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
@property (nonatomic, strong) NSNumber *numberField;
@property (nonatomic, strong) NSURL *urlField;

@property (nonatomic, strong) id idField;
@property (nonatomic, strong) id <NSObject> idProtocolField;


// This property is not included in the mapping
@property (nonatomic, strong) NSString *privateStringField;
Expand Down
3 changes: 3 additions & 0 deletions SampleProject/Motis Tests/MJTestObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ + (NSDictionary*)mts_mapping
@"number": mts_key(numberField),
@"url": mts_key(urlField),

@"id": mts_key(idField),
@"id_protocol": mts_key(idProtocolField),

@"string1.string2.string3" : mts_key(stringField),
@"url1.url2.url3" : mts_key(urlField),
};
Expand Down
44 changes: 44 additions & 0 deletions SampleProject/Motis Tests/Motis_Tests.m
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,30 @@ - (void)testNumberToString
}
}

#pragma mark to id

- (void)testNumberToId
{
for (NSNumber *number in [self mts_arrayWithNumbers])
{
_object.idField = nil;
[_object mts_setValue:number forKey:@"id"];
if (![_object.idField isEqualToNumber:number])
XCTFail(@"Failed to map number value %@", number.description);
}
}

- (void)testNumberToIdProtocol
{
for (NSNumber *number in [self mts_arrayWithNumbers])
{
_object.idField = nil;
[_object mts_setValue:number forKey:@"id_protocol"];
if (![(NSNumber*)_object.idProtocolField isEqualToNumber:number])
XCTFail(@"Failed to map number value %@", number.description);
}
}

#pragma mark - FROM STRING

// ------------------------------------------------------------------------------------------------------------------------ //
Expand Down Expand Up @@ -274,6 +298,26 @@ - (void)testStringToUrl
XCTFail(@"Failed to map string value %@", string);
}

#pragma mark to id

- (void)testStringToId
{
NSString *string = @"Hello World";
[_object mts_setValue:string forKey:@"id"];

if (![_object.idField isEqualToString:string])
XCTFail(@"Failed to map string value %@", string);
}

- (void)testStringToIdProtocol
{
NSString *string = @"Hello World";
[_object mts_setValue:string forKey:@"id_protocol"];

if (![(NSString*)_object.idProtocolField isEqualToString:string])
XCTFail(@"Failed to map string value %@", string);
}

#pragma mark - FROM DICTIONARY

// ------------------------------------------------------------------------------------------------------------------------ //
Expand Down
2 changes: 1 addition & 1 deletion SampleProject/Motis/MJAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ @implementation MJAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//[self performTest]; // <--- UNCOMMENT FOR TESTING
[self performTest]; // <--- UNCOMMENT FOR TESTING

UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = [[UIViewController alloc] init];
Expand Down
2 changes: 2 additions & 0 deletions SampleProject/Motis/MJUser.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#import <Foundation/Foundation.h>

#import "Motis.h"

@interface MJUser : NSObject

@property (nonatomic, assign) NSNumber *userId;
Expand Down
5 changes: 3 additions & 2 deletions SampleProject/Motis/MJVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#import <Foundation/Foundation.h>

@class MJUser;
#import "MJUser.h"

/** ********************************************************* **
* @name JSON Entity Attributes
Expand Down Expand Up @@ -62,8 +62,9 @@

/**
* Title of the video.
* @discussion Just for testing porpuses we set the NSString type as an id <NSObject>.
**/
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) id <NSObject> title;

/**
* Description of the video.
Expand Down

0 comments on commit c025711

Please sign in to comment.