NSMutableArray can not add object? - objective-c

I have 2 model:
#interface Program : NSObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, strong) NSMutableArray *guides;
#end
#interface Guide : NSObject
#property (nonatomic, retain) NSString *name;
#end
And I add some guides to program from one xml:
Program *program = [Program new];
program.name = #"My list"
for(DDXMLElement *guideElement in [programElement nodesForXPath:#"guide" error:&error])
{
Guide *guide = [Guide new];
guide.name = [guideElement stringValue];// [p attribute:#"name"];
[program.guides addObject:guide];
NSLog(#"load guide number: %d", [program.guides count]);
}
The out is always "load guide number: 0"

program.guides is nil, since you never created it.

In your Program's init method, add:
self.guides = [[NSMutableArray alloc] init];
Or, more sloppily, before your for loop add:
program.guides = [[NSMutableArray alloc] init];

Related

Objective C Acessing NSMutableDictionay inside NSMutableDictionary

I am a newcomer to objective C and I have serious problems in accessing NSMutableDictionarys.
I have two objects (Network and Beacon), and I want to create a NSMutableDictionary of Networks with a NSMutableDictionary of Beacons inside.
Network.h
#import <Foundation/Foundation.h>
#interface Network : NSObject{
NSString *id_network;
NSString *major;
NSString *active;
NSString *name;
NSString *status;
NSMutableDictionary *beaconsDictionary;
}
#property (nonatomic, strong) NSString *id_network;
#property (nonatomic, strong) NSString *major;
#property (nonatomic, strong) NSString *active;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *status;
#property (nonatomic, strong) NSMutableDictionary *beaconsDictionary;
#end
Beacon.h
#import <Foundation/Foundation.h>
#interface Beacon : NSObject{
NSString *id_beacon;
NSString *major;
NSString *minor;
NSString *active;
NSString *detected;
}
#property (nonatomic, strong) NSString *id_beacon;
#property (nonatomic, strong) NSString *major;
#property (nonatomic, strong) NSString *minor;
#property (nonatomic, strong) NSString *active;
#property (nonatomic, strong) NSString *detected;
#end
I can create the NSMutableDictionary like this:
Beacon *beacon = [[Beacon alloc]init];
beacon.id_beacon=#"1";
beacon.major=#"1";
beacon.minor=#"1";
beacon.active=#"1";
beacon.detected=#"0";
NSMutableDictionary *beaconDic = [[NSMutableDictionary alloc]init];
[beaconDic setObject:beacon forKey:beacon.id_beacon];
Network *net = [[Network alloc]init];
net.id_network=#"1";
net.major=#"1";
net.active=#"1";
net.name=#"network 1";
net.status=#"1";
net.beaconsDictionary=beaconDic;
NSMutableDictionary *networkDic = [[NSMutableDictionary alloc]init];
[networkDic setObject:net forKey:net.id_network];
Ok, but now how can i access to beacon property "detected" directly and modify it?
I know this this is a very bad example, but I have no idea how to do it.
It looks like you'll have to have a network id and a beacon id to get where you need to go. It would looks something like:
Network *net = networkDic[netId];
Beacon *beacon = net.beaconsDictionary[beaconId];
beacon.detected = newDetectedValue;
This is for arbitrary network ids and beacon ids. You can hardcode values if you wish.
Edit:
It's worth noting in your example code that you can use the more modern dictionary assignment. Rather than [dictionary setValue:value forKey:key];, you can do dictionary[key] = value;. It's, of course, personal preference but you're very likely to see the latter in more recent things and I find it to be clearer.
You can get your Network and Beacon objects back by providing keys that match their keys in the dictionary:
NSString *nwKey = #"1";
Network *n = networkDic[nwKey];
NSDictionary *bDict = n.beaconsDictionary;
NSString *bnKey = #"1";
Beacon *b = bDict[bnKey];
Note: This is the new syntax. Here is the old one:
NSString *nwKey = #"1";
Network *n = [networkDic objectForKey:nwKey];
NSDictionary *bDict = n.beaconsDictionary;
NSString *bnKey = #"1";
Beacon *b = [bDict objectForKey:bnKey];

Working faster with variables that have almost the same name

Really strange question but I just can't find the right way to do this on the internet my self.
I have 3 NSStrings. called: string1, string2 and string3.
They all get value from the same UITextfield but at different times. So the values are different from each other.
What happens now is:
-(void)statement {
if (i==0) {
string1 = nameField.text;
} else if (i==1) {
string2 = nameField.text;
} else if (i==2) {
string3 = nameField.text;
}
}
Is it possible to replace the 1,2 and 3 of behind the 'string' with a variable or something so I can say something like:
-(void)statement {
stringX = nameField.text;
}
So that I can change X before the statement is activated?
Hope that it's all clear!
Thanks!
Declare a mutable array called, for example, myString
NSMutableArray *myString = [[NSMutableArray alloc] init];
then use something like
myString[i] = nameField.text
If those strings are properties on an object, you can use KVO:
#property (nonatomic, strong) NSString *string1;
#property (nonatomic, strong) NSString *string2;
#property (nonatomic, strong) NSString *string3;
Setter:
[object setValue:nameField.text forKey:[NSString withFormat:#"string%#", #(i)]];
Or create a selector and perform it:
// assuming
#property (nonatomic, strong) NSString *string1;
#property (nonatomic, strong) NSString *string2;
#property (nonatomic, strong) NSString *string3;
// then
-(void)statement {
NSString *selName = [NSString withFormat:#"setString%#", #(i)];
SEL sel = NSSelectorFromString(selName);
[self performSelector:sel withObject:nameField.text afterDelay:0];
}

serialize objective-c custom object to JSON for OSX?

I'm very new to Mac development and I'm having some troubles finding good resources. My current problem is a custom objective-c class object serialization to JSON.
I know that there is a built-in serializer in apple libraries, but that one works only with Foundation objects.
In my case I have my own class that looks like this:
#interface SomeClass : NSObject
{
int a;
int b;
NSString *aa;
NSString *bb;
}
#property int a,b;
#property NSString *aa,*bb;
#end
If anyone knows how to serialize this type of structure to a JSON please give me a hint! Any kind of relevant information would help! Thank you!
If you just want to serialize an object that contains integers and strings, the easiest way is to create a data structure that NSJSONSerialization supports and serialize that:
static const NSString *kAKey = #"a";
static const NSString *kBKey = #"b";
static const NSString *kAaKey = #"aa";
static const NSString *kBbKey = #"bb";
- (id)JSONObject {
return #{
kAKey: #(self.a),
kBKey: #(self.b),
kAaKey: self.aa,
kBbKey: self.bb
};
}
- (NSData *)JSONData {
return [NSJSONSerialization dataWithJSONObject:[self JSONObject] options:0 error:NULL];
}
I have been looking into this for the past week. I decided to write my own solution. It is very simple and built upon existing Apple functionality.
See here: https://github.com/gslinker/GSObject
And here: http://digerati-illuminatus.blogspot.com/2016/01/objective-c-and-json-convert-subclass.html
For your data model object have it inherit from GSObject instead of NSObject. Here is an example of ThingOne with inherits from GSObject:
ThingOne* object1 = [[ThingOne alloc] init];
object1.name = #"John Jones";
NSData* jsonData1 = [object1 toJsonDataWithOptions:NSJSONWritingPrettyPrinted];
NSString *jsonString1 = [object1 toJsonStringWithOptions:NSJSONWritingPrettyPrinted];
NSDictionary<NSString *,id> *dict1 = [GSObject dictionaryWithValues:object1];
NSString *roundTripJson1 = [object1 toJsonStringWithOptions:NSJSONWritingPrettyPrinted];
//
// ThingOne.h
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GSObject.h"
#import "ThingTwo.h"
#interface ThingOne : GSObject
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) ThingTwo *thingTwo;
#property (nonatomic, retain) NSArray *values;
#property (nonatomic, retain) NSDictionary *dict;
#property int myInt;
#property float myFloat;
#property BOOL myBool;
#property (nonatomic, retain) NSNumber* someMoney;
#end
//
// ThingOne.m
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import "ThingOne.h"
#implementation ThingOne
#synthesize name;
#synthesize thingTwo;
#synthesize values;
#synthesize dict;
#synthesize myInt;
#synthesize myFloat;
#synthesize myBool;
#synthesize someMoney;
- (instancetype)init
{
self = [super init];
thingTwo = [[ThingTwo alloc] init];
thingTwo.stuff = #"Thing Two Stuff";
thingTwo.someOtherStuff = #"Thing Two Other Stuff";
NSDateFormatter *dateFormater = [[NSDateFormatter alloc]init];
[dateFormater setDateFormat:#"yyyy-mm-dd"];
thingTwo.someDate = [dateFormater dateFromString:#"1963-10-07"];
values = [NSArray arrayWithObjects:#"Value1", #"Value2", #"Value3", nil];
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"value1", #"key1", #"value2", #"key2", nil];
myInt = 5431;
myFloat = 123.456f;
myBool = YES;
someMoney = [NSNumber numberWithInt:503];
return self;
}
#end
//
// ThingTwo.h
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GSObject.h"
#interface ThingTwo : GSObject
#property (nonatomic, retain) NSString *stuff;
#property (nonatomic, retain) NSString *someOtherStuff;
#property (nonatomic, retain) NSDate *someDate;
#property (nonatomic, retain) NSString *nullString;
#property (nonatomic, retain) NSDate *nullDate;
#end
//
// ThingTwo.m
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import "ThingTwo.h"
#implementation ThingTwo
#synthesize stuff;
#synthesize someOtherStuff;
#synthesize someDate;
- (instancetype)init
{
self = [super init];
someDate = [NSDate date];
return self;
}
#end
Here is an example of the JSON output:
{
"values" : [
"Value1",
"Value2",
"Value3"
],
"myInt" : 5431,
"myFloat" : 123.456,
"myBool" : true,
"someMoney" : "$503.00",
"thingTwo" : {
"stuff" : "Thing Two Stuff",
"nullDate" : null,
"someDate" : "1963-01-07 07:10:00 +0000",
"nullString" : null,
"someOtherStuff" : "Thing Two Other Stuff"
},
"name" : "John Jones",
"dict" : {
"key1" : "value1",
"key2" : "value2"
}
}

Problem creating NSManagedObject derived class

I am doing something wrong here... I know that
I'm using Xcode and I have created the following class using the data modeller:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Project : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * indent;
#property (nonatomic, retain) NSNumber * collapsed;
#property (nonatomic, retain) NSString * color;
#property (nonatomic, retain) NSNumber * project_id;
#property (nonatomic, retain) NSNumber * item_order;
#property (nonatomic, retain) NSNumber * cache_count;
#property (nonatomic, retain) NSNumber * user_id;
#property (nonatomic, retain) NSString * name;
#end
When I am trying to propagate this class with data from a JSON source using the following code:
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"projects" ofType:#"json"];
if (filePath) {
NSString* jsonString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
DLog(#"JSON for Projects:%#", jsonString);
SBJsonParser* jsonParser = [SBJsonParser new];
id response = [jsonParser objectWithString:jsonString];
NSArray* array = (NSArray*) response;
NSEnumerator* e = [array objectEnumerator];
NSDictionary* dictionary;
while ((dictionary = (NSDictionary*)[e nextObject])) {
Project* project = [[Project alloc] init];
project.user_id = [dictionary objectForKey:#"user_id"];
project.name = [dictionary objectForKey:#"name"];
project.color = [dictionary objectForKey:#"color"];
project.collapsed = [dictionary objectForKey:#"collapsed"];
project.item_order = [dictionary objectForKey:#"item_order"];
project.cache_count = [dictionary objectForKey:#"cache_count"];
project.indent = [dictionary objectForKey:#"indent"];
project.project_id = [dictionary objectForKey:#"project_id"];
[elementArray addObject:project];
[project release];
}
}
However, the code stops at the project.user_id = [dictionary objectForKey:#"user_id"]; line with an exception "* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Project setUser_id:]: unrecognized selector sent to instance 0x590bcb0'"
I don't know why this is happening or how to resolve this.
I've set up a reality distortion field so I don't violate my NDA. And now I can answer your question, it has nothing to do with the product-that-must-not-be-named anyway.
There is your bug: Project* project = [[Project alloc] init];
The #dynamic setters and getters are not created for you if you create your object this way.
You can't use NSManagedObjects without a NSManagedObjectContext.
You should use something like this:
Project *project = (Project *)[NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:self.managedObjectContext];
Property names with underscores are not very sensible in the Objective C world - I guess the properties generated by Core Data have the wrong names therefore. Try using CamelCase, that is calling your properties userID, itemOrder, cacheCount etc.
You may need to set up your getters and setters.
It could be as simple as adding:
#synthesize user_id;
In your class file.

Does this copy class method leak memory?

- (id)copyWithZone:(NSZone *)zone {
PoolFacility *copy = [[[self class] allocWithZone:zone]init];
copy.name = [self.name copy];
copy.type = [self.type copy];
copy.phoneNumber = [self.phoneNumber copy];
//make sure I get proper copies of my dictionaries
copy.address = [self.address mutableCopy];
copy.webAddress = [self.webAddress copy];
copy.prices = [self.prices mutableCopy];
copy.pools = [self.pools mutableCopy];
return copy;
}
Can anyone see any memory leaks?
Here's the property types:
NSString *name;
NSString *type;
NSMutableDictionary *address;
NSString *phoneNumber;
NSString *webAddress;
NSMutableArray *prices;
NSMutableArray *pools;
Here are the property declarations:
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *type;
#property (nonatomic, copy) NSString *phoneNumber;
#property (nonatomic, retain) NSMutableDictionary *address;
#property (nonatomic, copy) NSString *webAddress;
#property (nonatomic, retain) NSMutableArray *prices;
#property (nonatomic, retain) NSMutableArray *pools;
The properties defined as copy and not retain will have an extra copy when set as below (your code)
copy.name = [self.name copy];
copy.type = [self.type copy];
copy.phoneNumber = [self.phoneNumber copy];
copy.webAddress = [self.webAddress copy];
it should be sufficient to only write them as
copy.name = self.name;
copy.type = self.type;
copy.phoneNumber = self.phoneNumber;
copy.webAddress = self.webAddress;
This almost certainly leaks like a sieve. You need to provide your #property and other method declarations for us to recommend the best way to fix it.