Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Objective C syntax (lightweight generics) #376

Closed
pjebs opened this issue Sep 22, 2015 · 16 comments
Closed

New Objective C syntax (lightweight generics) #376

pjebs opened this issue Sep 22, 2015 · 16 comments

Comments

@pjebs
Copy link

pjebs commented Sep 22, 2015

In the new version of Objective C (on XCode 7), we can now specify what a NSArray can contain.

Will your library support this? It will definitely reduce the amount of casting we need to do.

Say we have a JSONModel subclass called Cars.

Say we have another JSONModel subclass called Person:

@Property (strong, nonatomic) NSArray < Cars * > * cars; //Restricting NSArray to Cars

rather than currently:

@protocol Cars
@EnD

@Property (strong, nonatomic) NSArray < Cars > * cars; //Currently

@vaddieg
Copy link

vaddieg commented Sep 23, 2015

W/ Xcode 7 you have to forward-declare protocol name explicitly to suppress compiler error

@MellongLau
Copy link

Hope @pjebs opinion can be accepted.

@MellongLau
Copy link

Find the answer : http://stackoverflow.com/questions/30866197/how-can-i-find-out-the-objective-c-generics-type

The lightweight generics introduced in Xcode 7 are just compile time hints to help the compiler raise warnings, but at run time you get the same old behavior with your variable being just NSArrays of ids.

So, I think it is not possible to do some thing like that.

@ghost
Copy link

ghost commented Oct 16, 2015

Workaround:

@interface Model: JSONModel
@property (strong, nonatomic) NSArray < Cars * > * cars;
@end

@implementation Model
- (void)setCars:(NSArray<NSDictionary*> *)cars {
    NSMutableArray* mutArray = [NSMutableArray array];

    for (NSDictionary* carDict in cars) {
        NSError* error;
        Cars* car = [[Cars alloc] initWithDictionary:carDict error:&error];

        if (car && !error) {
            [mutArray addObject:car];
        }
    }

    _cars = [NSArray arrayWithArray:mutArray];
}
@end

Unfortunly you need to do this with every array.

@jkmathew
Copy link
Contributor

I also tried this by adding new type annotation(with generics) with arrays, but its not giving any information about the added annotation/generics in runtime.
That is while fetching property attributes with property_getAttributes() its not giving any information about the annotation.

@icanzilb , @dbachrach do you have any thoughts about this?

@dbachrach
Copy link
Collaborator

Yeah, the objc generics implementation does not persist data at runtime, so it's not usable to JSONModel.

@skerkewitz
Copy link

Looks to me like it is even worse:

If you do:

@protocol Cars
@end
@property (strong, nonatomic) NSArray <Cars> *cars; // JSONModel way

then Swift will map cars to [AnyObject] as Swift does not know the type.

If you do:

@property (strong, nonatomic) NSArray <Cars *> *cars; 

Then swift will map it to [Cars] but JSONModel will not parse the json correctly as it does not know the type. So it seems like you can't have both.

@pjebs
Copy link
Author

pjebs commented Oct 26, 2015

I turns out you can have both (I think).
<cars *, cars>

@MellongLau
Copy link

@pjebs, you can not do that, it will cause compile error.

@vaddieg
Copy link

vaddieg commented Oct 27, 2015

Fortunatelly, you can use C macro w/ setCars: workaround
#define JSON_SETTER(className, propName)

@pjebs
Copy link
Author

pjebs commented Oct 27, 2015

@vaddieg can you elaborate and give more details of usage?

@vaddieg
Copy link

vaddieg commented Oct 27, 2015

Very draft marco, w/o error checking

#import "JSONModel.h"

#define JSONSetterImp(setterSignarure, ClassName, ivarName) \
- (void) setterSignarure :(NSArray<NSDictionary*> *)array {\
    NSMutableArray *ma = [NSMutableArray arrayWithCapacity:array.count];\
    for (NSDictionary* object in array) { \
        ClassName *model = [[ClassName alloc] initWithDictionary:object error:NULL]; \
        if (model) { \
            [ma addObject:model]; \
        } \
    } \
    ivarName = [ma copy];\
}

@interface Car : JSONModel
@end

@interface Parking : JSONModel
@property (strong, nonatomic) NSArray<Car*> *cars;

@end

And Implementation of setter will look like:

@implementation Parking

JSONSetterImp(setCars, Car, _cars)

@end

@pjebs
Copy link
Author

pjebs commented Nov 4, 2015

I have verified that you can do this:
<cars *><cars>

@MellongLau
Copy link

@pjebs GOOD JOB.

@vaddieg
Copy link

vaddieg commented Nov 4, 2015

@pjebs Nice. Case is closed I think

@vaddieg
Copy link

vaddieg commented Nov 7, 2015

@icanzilb pls update Readme.md Model Collection example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants