objective c class property variables not populated - objective-c

I have the following simple class definition:
//mycommon.h
#interface CurrentPath : NSObject
#property (nonatomic, strong) NSString* PathString;
#property (nonatomic, strong) NSMutableArray* PathArr;
- (void) addAddressToPath:(NSString*) address;
#end
//mycommon.m
#implementation CurrentPath : NSObject
#synthesize PathString;
#synthesize PathArr;
- (void) addAddressToPath:(NSString*) address{
NSLog(#"addAddressToPath...");
// Add to string
self.PathString = [self.PathString stringByAppendingString:address];
// Add to Arr
[self.PathArr addObject:address];
}
#end
In another class I do #import<mycommon.h> and declare the variable like this:
#interface myDetailViewController :
{
CurrentPath* currentPath;
}
- (void) mymethod;
#end
and in
#implementation myDetailViewController
- void mymethod{
self->currentPath = [[CurrentPath alloc] init];
NSString* stateSelected = #"simple";
[self->currentPath addAddressToPath:stateSelected];
}
#end
Problem is that the PathString and PathArr properties of self->currentPath are empty after this method call which I think should have "simple" in them. Please help!

You have to make sure that your NSString and NSMutableArray properties are initialized when your CurrentPath object is created. Otherwise, the call to stringByAppendingString will result in nil because it is sent to a nil object.
One feasible way would perhaps be
self.currentPath = [NSString string];
// or
self.currentPath = #"";
[self.currentPath addAddressToPath:#"simple"];
More elegant and robust would be to check for nil property in the addAddressToPath method.
if (!self.pathString) self.pathString = [NSString string];
if (!self.pathArr) self.pathArr = [NSMutableArray array];
Notice that am following the objective-c convention and use property names that start with lower case letters.

Related

Objective-C Where to define initial Class Properties

just wanted to ask where I define initial class properties?
From other languages I am used to define some standard properties in the head before the content of the class starts.
For example paths to files. Settings and so on.
Where I fill these initial properties with values in Objective-C?
Thanks
Generally it's something like:
MyClass.h:
extern NSString * const staticValue1;
extern NSString * const staticValue2;
#interface MyClass : NSObject
{
NSString *_strval;
int _intval;
float _fltval;
}
#property (retain, nonatomic, readwrite) NSString *strval;
#property (assign, nonatomic, readwrite) int intval;
#property (assign, nonatomic, readwrite) float fltval;
#end
MyClass.m:
NSString * const staticValue1 = #"Something";
NSString * const staticValue2 = #"Something else";
#interface MyClass
#synthesize strval = _strval;
#synthesize intval = _intval;
#synthesize fltval = _fltval;
- (id)init
{
self = [super init];
if (self != nil)
{
[self setStrval:[NSString stringWithFormat:#"This is a %#", #"string"]];
[self setIntval:10];
[self setFltval:123.45f];
}
return self;
}
- (void)dealloc
{
[self setStrval:nil];
[super dealloc];
}
#end
This demonstrates the use of synthesized properties which are being used here to manage the memory of the instance variable _strval, which requires retaining/releasing to avoid memory leaks. Note that [self setStrval] is initialised with an autoreleased object (from [NSString stringWithFormat) and will be retained by the setter method. Alternatively these methods can be called using the following syntax, if you prefer:
self.strval = [NSString stringWithFormat:#"This is a %#", #"string"];
self.intval = 10;
self.fltval = 123.45f;
Maybe some of what you are after can be implemented with class methods.
Class methods are coded with a + (instead of the instance methods' -), and can't refer to instance variables, as they are not associated with any specific instance of the class.
This is a class method to return a default string:
+ (NSString *)myDefaultString
{
return #"Some default value";
}
You call it by simply calling it with the class name at the receiver's place. Imagine you have defined the method in a class called MyClass, the you call it like this:
NSString *str = [MyClass myDefaultString];
You'll notice that there is no alloc/init calls in this.
Public property needs to be define in .h file.
#interface MyClass {
}
#property(nonatomic, reatin) NSString *a;//Define as per needs, then synthesise in .m file
#end
For private property you need define inline category in .m file-
#interface MyClass ()
#property(nonatomic, reatin) NSString *b;//Define as per needs, then synthesise in .m file
#end
#implementation MyClass
#synthesize a = _a;
#synthesize b = _b;
- (void)viewDidLoad {
//You can initialise property here or in init method
self.a = #"Demo1";
self.b = #"Demo2";
}
//Now you can have other code for this class.
#end

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)

Strange assignment in synthesize

I have seen a lot of code like this
header.h
#interface Foo : NSObject
{
NSString *str;
}
#property(nonatomic, retain) NSString *str;
#end
and then in implementation
#implementation Foo
#synthesize str = _str;
#end
I can't understand what is the benefit of using such assignment ?
#synthesize str = _str;
It is just a common naming convention.
It is so that in your implementation, you can distinguish accessing a variable directly against accessing via the property accessor.
If you try and access str in your code, like [str length], the code won't compile. You either need to do [self.str length] or [_str length].
... and as it's an NSString immutable property, use copy, not retain.
#synthesize str = _str; will mean that the instance variable that is synthesised for the str property is called _str. In your code you therefore have a mismatch between it and the declared instance variable. So you'll actually end up with 2 instance variables, one called str and one called _str.
You want to do this:
#interface Foo : NSObject
#property(nonatomic, retain) NSString *str;
#end
#implementation Foo
#synthesize str = _str;
#end
Or this:
#interface Foo : NSObject {
NSString *str;
}
#property(nonatomic, retain) NSString *str;
#end
#implementation Foo
#synthesize str;
#end
Or obviously rename the declared instance variable, _str.
There's lots of questions on SO already about whether or not to prefix with _ such as - Prefixing property names with an underscore in Objective C .
Here's a quick example of how it can be useful to use the name change:
#interface MyClass : NSObject {
NSString *myString;
}
#property (nonatomic, retain) NSString *myString;
- (NSString *)stringTreatment:(NSString *)str;
#end
#implementation MyClass
#synthesize str = _str;
- (id)init {
self = [super init];
if (self) {
self.str = [NSString string];
}
return self;
}
- (NSString *)stringTreatment:(NSString *)str {
return [str uppercaseString];
}
#end
If you wouldn't have synthesized str as _str, you would get a warning in that stringTreatment method saying that the local declaration of str hides the instance variable.
Also, in your code, you could be assigning a value to _str and have an external class call [MyClass str] and it would return it.
So, to make a long story short, "str" remains the name of your property and "_str" is the internal reference to that property. For example, you won't be able to use [MyClass _str], that won't work. Makes sense?
Hope this helps.

How to access the object

I would like to access the the _news items in a loop. But don't know how to get this done.
My Game.m looks like
#import "Game.h"
#implementation Game
#synthesize homename = _homename;
#synthesize guestname = _guestname;
#synthesize date = _date;
#synthesize gametype = _gametype;
#synthesize news = _news;
#synthesize gameId = _gameId;
-(NSString*)description{
return [NSString stringWithFormat:#"%# gegen %# (%#)", self.homename, self.guestname, self.gametype];
}
#end
My Game.h looks like
#import <Foundation/Foundation.h>
#import <RestKit/RestKit.h>
#import "News.h"
#interface Game : NSObject {
NSString* _homename;
NSString* _guestname;
NSString* _date;
NSString* _gametype;
NSNumber* _gameId;
// News* news;
#public
NSArray* _news;
}
#property (nonatomic, retain) NSString* homename;
#property (nonatomic, retain) NSString* guestname;
#property (nonatomic, retain) NSString* date;
#property (nonatomic, retain) NSString* gametype;
//#property (nonatomic, retain) News* news;
#property (nonatomic, retain) NSArray* news;
#property (nonatomic, retain) NSNumber* gameId;
#end
My News.h looks like
#import <Foundation/Foundation.h>
#import <RestKit/RestKit.h>
#interface News : NSObject {
NSString* _minute;
NSString* _title;
NSString* _bodytext;
NSString* _player;
}
#property (nonatomic, retain) NSString* minute;
#property (nonatomic, retain) NSString* title;
#property (nonatomic, retain) NSString* bodytext;
#property (nonatomic, retain) NSString* player;
#end
My news.m looks like
#import "News.h"
#implementation News
#synthesize player = _player;
#synthesize title = _title;
#synthesize bodytext = _bodytext;
#synthesize minute = _minute;
#end
And the code where I want to access the variable looks like:
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
NSLog(#"Loaded statuses: %#", objects);
HeaderText.text = [NSString stringWithFormat:#"%#", objects ];
// for(News* n in _news) NSLog([n _bodytext]);
// for (id object in objects) {
// NSLog(#"News = %#", object );
// }
}
The NSLog with objects looks good for the game. The next thing is that I want to do something like (above is more pseudo code than real code because I don't know how to do it right):
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
NSLog(#"Loaded statuses: %#", objects);
HeaderText.text = [NSString stringWithFormat:#"%#", objects ];
// loop all
for (id object in objects) {
news = objects.news;
for (id mynews in news) {
NSLog(#"News minute = %#", news.minute );
NSLog(#"News title = %#", news.title );
NSLog(#"News bodytext = %#", news.bodytext );
NSLog(#"News player = %#", news.player );
}
}
}
How to do the getter/setter methods right (so that I can use it here)?
Sorry for the surely stupid question but I don't get the point with it.
Two things:
1stly, is the _news object a private variable, without having a property declaration (getters and setters for e.g.)? The '_variableName' format is usually used to denote private variables.
2ndly, if it is not a private variable, do all the items within the _news array belong to the same class?
If so, you can do a
for (NewsObject *theNewsObject in _news)
{
//code here
}
The for(id randomObject in array) is useful when you don't know what type of object is in the array or if the objects contained in the array are of different types.
Now, again, all the objects inside the NewsObject ought to be public properties that can be accessed by other classes (they should have getters and setters).
Hope this helps. :)
EDIT FOR UPDATED QUESTION
So, if I'm getting your question correctly, you have a Game object, which has an array of News object inside it.
So, in your Game.h
NSString* _homename;
NSString* _guestname;
NSString* _date;
NSString* _gametype;
NSNumber* _gameId;
NSArray * _newsObjects; //declare it as NSMutableArray if you need to mutate it
Now, where you declare your properties;
#property(nonatomic, retain)NSArray *newsObjects
Synthesize it like you normally would in the Game.m file
You are creating the getters/setters automatically by using the #synthesize directive. It creates the getters and setters for you.
Again, from your code, it looks like the NSArray of objects that are passed through the method
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
consist of Game objects.
So, to access the News object from within the array of Game objects, import News.h and Game.h in the class where this method is being executed, and do the following:
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
NSLog(#"Loaded statuses: %#", objects);
// loop all
for (Game *gameObject in objects) {
NSArray *newsObjectArray = [gameObject newsObjects] //or gameObject.newsObject
for (News *mynews in newsObjectArray) {
NSLog(#"News minute = %#", mynews.minute );
NSLog(#"News title = %#", mynews.title );
NSLog(#"News bodytext = %#", mynews.bodytext );
NSLog(#"News player = %#", mynews.player );
}
}
}
What I found in your code that there was code that was being executed which was not declared in any part of the example that you posted.
What the code above will do is it will look through the Game object array (called objects).
Then, for each gameObject within that array, it will loop through the array of newsObject for that gameObject.
Hope this helps. :)

Objective-C dot syntax or property value?

I keep reading that dot syntax is possible but I keep getting errors that the struct does not contain members I am referencing. Perhaps its not the dot syntax so I have included details of what I am doing in hopes of a solution:
// MobRec.h - used as the objects in the MobInfo array
#import <Foundation/Foundation.h>
#interface MobRec : NSObject {
#public NSString *mName;
#public int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
// MobDefs.h - array of MobRecords
#interface Mobdefs : NSObject {
#public NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo; // is this the right property?
-(void) initMobTable;
#end
// MobDefs.m
#import "Mobdefs.h"
#import "Mobrec.h"
#implementation Mobdefs
#synthesize mobInfo;
-(void) initMobTable
{
// if I use traditional method I get may not respond
[mobInfo objectAtIndex:0 setmName: #"doug"];
// if I use dot syntax I get struct has no member named mName
mobInfo[1].MName = #"eric";
}
// main.h
MobDefs *mobdef;
// main.m
mobdef = [[Mobdefs alloc] init];
[mobdef initMobTable];
although both methods should work I get erros on both. What am I doing wrong? My best thoughts have been that I am using the wrong #property but I think I have tried all. I am performing alloc in main. Ideally I would like to for this use dot syntax and cant see why its not allowing it.
A couple of things: (edit: original point #1 removed due to error)
Although the dot syntax is supported, the array index syntax for NSArray is not. Thus, your call to mobInfo[1] will not be the same as [mobInfo objectAtIndex:1]; Instead, mobInfo will be treated as a simple C-style array, and that call would be almost guaranteed to result in a crash.
You should not define variables in your header file as you do in main.h. The line MobDefs *mobdef; belongs somewhere in main.m.
edit: Here is how it should look:
MobRec.h
#interface MobRec : NSObject {
NSString *mName;
int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
MobRec.m
#implementation MobRec
#synthesize mName;
#synthesize mSpeed;
#end
MobDefs.h
#interface MobDefs : NSObject {
NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo;
-(void) initMobTable;
#end
MobDefs.m
#import "MobDefs.h"
#import "MobRec.h"
#implementation MobDefs
#synthesize mobInfo;
-(void) initMobTable
{
// option 1:
[(MobRec*)[mobInfo objectAtIndex:0] setMName:#"doug"];
// option 2:
(MobRec*)[mobInfo objectAtIndex:0].mName = #"eric";
// option 3:
MobRec *mobRec = [mobInfo objectAtIndex:0];
mobRec.mName = #"eric";
}
main.m
MobDef *mobdef = [[MobDefs alloc] init];
[mobdef initMobTable];
...
[mobdef release]; // don't forget!
You need to either cast the object returned by -objectAtIndex:, or use a method call on it:
[[mobInfo objectAtIndex: 0] setMName: #"doug"];
or
((Mobrec *) [mobInfo objectAtIndex: 0]).MName = #"doug";
[mobInfo objectAtIndex:0 setmName: #"doug"];
There is no objectAtIndex:setmName method, so you're going to have to explain what you think this is even supposed to do.
mobInfo[1].MName = #"eric";
Use objectAtIndex to look something up in an NSArray object.