Creating an enum from NSDictionary - objective-c

Suppose I have an enum as follows:
typedef enum {
FooGoods = 0,
FooInsurance = 1,
} FooCategory;
And I have it as property and ivar in another object
#property (nonatomic) FooCategory *category;
When I create that other object, I am filling with values from an NSDictionary So I do something like this:
[baz setCategory:[aDictionary objectForKey:#"Category"]];
However because my enum is not a pointer, I get an error.
Doing this get a warning as well, "Incompatible integer to pointer conversion":
[baz setCategory:[[aDictionary objectForKey:#"Category"] intValue]];
Any other way that is error/warning free?

The following is not correct
#property (nonatomic) FooCategory *category;
should be changed to
#property (nonatomic) FooCategory category;
Now this should work without warnings
baz.category = (FooCategory)[aDictionary objectForKey:#"Category"] intValue];

Related

Can't find a appropriate property attribute for a instance variable

I'm new to this objective-c property attribute thing. Here's the code:
student.h
#import <Foundation/NSObject.h>
#interface Student: NSObject
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
-(Student*) initWithName: (NSString *) n andAge:(int) a;
-(void) speakName;
+(void) smoke:(NSString*) thing;
#end
student.m
#import "student.h"
#implementation Student
-(Student*) initWithName:(NSString*) n andAge:(int) a {
self = [super init];
if(self) {
[self setName: n];
[self setAge: a];
}
return self;
}
-(void) speakName {
NSLog(#"MyName is %#", _name);
}
+(void) smoke:(NSString*) thing {
NSLog(#"Smoking %#", thing);
}
#end
main.m
#import <Foundation/Foundation.h>
#import "student.h"
int main(void) {
Student *student = [[Student alloc] initWithName: #"Markson" andAge: 29];
[student speakName];
[Student smoke:#"weed"];
[student release];
return 0;
}
for the the line
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
when I don't give nothing to them, the compiler give me 4 warnings:
In file included from student.m:1:
./student.h:5:1: warning: no 'assign', 'retain', or 'copy' attribute is
specified - 'assign' is assumed [-Wobjc-property-no-attribute]
#property NSString *name;
^
./student.h:5:1: warning: default property attribute 'assign' not appropriate
for non-GC object [-Wobjc-property-no-attribute]
2 warnings generated.
In file included from main.m:2:
./student.h:5:1: warning: no 'assign', 'retain', or 'copy' attribute is
specified - 'assign' is assumed [-Wobjc-property-no-attribute]
#property NSString *name;
^
./student.h:5:1: warning: default property attribute 'assign' not appropriate
for non-GC object [-Wobjc-property-no-attribute]
2 warnings generated.
Please anyone can tell what attributes should be used for age and name properties?
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
Short Note:
If you are creating property for primitive types like int, float, BOOL etc then use assign
If you want to retain the value then use strong or retain.
In all other situations you can go with weak.
And always go with atomic, and the syntax is like this
#property (<assign/retain/weak>, <atomic/nonatomic>, <read/readwrite>) <dataType> <propertyName>;
Change those lines to this:
#property (assign, nonatomic) int age;
#property (retain, nonatomic) NSString *name;
readwrite is the default one, so you don't need to set it.
Check this documentation:
Encapsulating data in Objective-C

Should I be creating a class instead of a struct so that I can put the data into an NSArray?

Is it possible to create something like a C struct for Objective-C? I need to be able to use it in an NSArray so it cannot be a traditional struct. Right now I am declaring a whole class just to accomplish this and I was wondering if there is a simpler way.
What I currently have:
#interface TextureFile : NSObject
#property NSString *name;
#property GLKTextureInfo *info;
#end
#implementation TextureFile
#synthesize name = _name;
#synthesize info = _info;
#end
NSMutableArray *textures;
What I want to do:
typedef struct {
NSString *name;
GLKTextureInfo *info;
} TextureFile;
NSMutable array *textures;
It depends what kind of data you're using, the example you are using in your question seems okay for a struct.
If you need to store a C struct in an NSArray, which requires an object, you can convert the C-struct to NSValue and store it like that, you then convert back to its C struct type when you read it.
Check the Apple Documentation.
Given this struct:
typedef struct {
NSString *name;
GLKTextureInfo *info;
} TextureFile;
To store it:
TextureFile myStruct;
// set your stuct values
NSValue *anObj = [NSValue value:&myStruct withObjCType:#encode(TextureFile)];
NSArray *array = [NSArray arrayWithObjects:anObj, nil];
To read it again:
NSValue *anObj = [array objectAtIndex:0];
TextureFile myStruct;
[anObj getValue:&myStruct];

Objective C: Compiler warning with enum

In myObject.h:
typedef enum {
GET,
POST
} HTTPMethods;
And then inside the #interface definition, a property:
#property (nonatomic) HTTPMethods *httpMethod;
In myClass.m, I have the #import of myObject.h and then:
myObject *obj = [[myObject alloc] init];
obj.httpMethod = POST;
This seems to work, but the compiler yells at me:
`Incompatible integer to pointer conversion assigning to 'HTTPMethods *' from 'int'.
Where am I going wrong here?
An enum is a built-in type, and not an object. As such, you probably want to store the integral value itself and not a pointer.
#property (nonatomic, assign) HTTPMethods httpMethod;
There's a big hint in the error message!
In C and Objective C, an enum is a user defined data type. You've written HTTPMethods *, which means "a pointer to an enum", whereas it looks like you just wanted an enum.
So change your property to this:
#property (nonatomic) HTTPMethods httpMethod;
For more info, google "C pointers" and you'll find information like this: http://pw1.netcom.com/~tjensen/ptr/pointers.htm

What does this warning mean in Xcode?

I have a resource which is fetched from a JSON API.
The JSON is parsed into a NSDictionary which, in this case is called game.
I'm creating a new instance of my Game class based on the attributes from the JSON.
Game class has a property called userRegistered which is defined as follows:
// in Game.h
#interface
#property (nonatomic, assign) BOOL userRegistered;
// elsewhere in my code I have
Game *newGame = [[Game alloc] init];
newGame.userRegistered = ([game objectForKey:#"user_registered"] > 0);
The "user_registered" key in the dictionary will always be either 1 or 0.
Xcode warns me the I have -
warning: Semantic Issue: Incompatible integer to pointer conversion passing 'int' to parameter of type 'BOOL *' (aka 'signed char *')
Can someone please explain the issue and how I might resolve it?
Update
My full game class is defined as follows:
#import <Foundation/Foundation.h>
#interface Game : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *photoURL;
#property (nonatomic, copy) NSString *gameURL;
#property (nonatomic, assign) BOOL *userRegistered;
#end
// Game.m
#import "Game.h"
#implementation Game
#synthesize name = _name;
#synthesize partnerName = _partnerName;
#synthesize photoURL = _photoURL;
#synthesize gameURL = _gameURL;
#synthesize userRegistered = _userRegistered;
#end
I'm getting the error in one of my ViewControllers in this method
// api_response.body has just been set to an __NSCFArray containing
// NSDictionaries by AFNetworking
NSDictionary *game;
Game *newGame;
for (game in api_response.body){
newGame = [[Game alloc] init];
NSLog(#"Creating a new game");
// set attributes for new game instance
newGame.name = [game objectForKey:#"name"];
newGame.photoURL = [game objectForKey:#"photoURL"];
// user registered is either 0 (false) or 1 (true)
newGame.userRegistered = [[game objectForKey:#"user_registered"] intValue];
// add the game instance to the appropriate array
[self addGameToGamesArray:newGame];
newGame = nil;
}
The warning shows over newGame.userRegistered = [[game objectForKey:#"user_registered"] intValue];
[game objectForKey:#"user_registered"] is likely giving you an NSNumber object. You probably mean instead to compare the integer value inside that NSNumber object.
([[game objectForKey:#"user_registered"] intValue] > 0)
UPDATE in response to your update:
Your problem is with how you're declaring your BOOL property - you have a * that you need to remove.
#property (nonatomic, assign) BOOL *userRegistered;
should be
#property (nonatomic, assign) BOOL userRegistered;
I was able to solve this issue by simply using boolValue
game.userRegistered = [[json objectForKey:#"user_registered"] boolValue];
Thanks all for the help
objectForKey function will return an objective-c instance.
([[game objectForKey:#"user_registered"] boolValue] > 0)
([game boolForKey:#"user_registered"]==YES)

obj-c, how do I create a property and synthesize an NSUInteger?

I'm having some trouble using an NSUInteger, I've tried various things and googled, but not found the answer ?
I have... I also tried ... nonatomic, retain
#property (readwrite, assign) NSUInteger *anAmount;
#synthesize anAmount;
error: type of property 'anAmount' does not match type of ivar 'anAmount'
Also when I release it in dealloc I get a warning..
warning: invalid receiver type 'NSUInteger'
Remove the * if you're not intending to use a pointer to an NSUInteger (which is a value type, and not a pointer type):
#property (readwrite, assign) NSUInteger anAmount;
And do not release it.
Another possibility is to use NSNumber declaring and initializing below. NSNumber provides some helper methods that may be of interest to you.
#property (readwrite, copy) NSNumber showMeTheMoney;
showMeTheMoney = [NSNumber numberWithUnsignedInt:1234567890];