Can't use NSMutableArray data after Parsing with NSXMLParser (objective-c) - objective-c

Hi I did parsing with NSXMLParser of some xml :
<company>
<name>Idan</name>
<country>Israel</country>
.....
<gender>man</gender>
</company>
I see that parsing success , now I have the MutableArray with one object that contain all strings (Idan,Israel etc.) but when I want to use this array, I can't get strings it contain.
When I do :
NSMutableArray *use = [pars users ];
NSLog(#"%#",use );
(users it's my array with object) I see:
<List:03f5a78>
where List in my code is:
#import <Foundation/Foundation.h>
#interface List : NSObject{
NSString *name;
NSString *country;
NSString *status;
NSString *gender;
}
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *country;
#property (nonatomic, strong) NSString *status;
#property (nonatomic, strong) NSString *gender;
#end
#import "List.h"
#implementation List
#synthesize name,date,city,country,status, gender;
#end
I try to do something like this:
NSMutableArray *use = [pars users.name ];
NSLog(#"%#",use );
but is not working, any ideas how to fix this?

Override the description method of your List class, and return a string which includes the values of all of the properties, then output it like you did the first time. The console will then print the value you returned.
Example:
#implementation List
...
...
-(NSString *)description
{
NSMutableString *desc = [NSMutableString string];
[desc appendFormat:#"name=%#, ", self.name];
[desc appendFormat:#"country=%#, ", self.country];
[desc appendFormat:#"status=%#, ", self.status];
[desc appendFormat:#"gender=%#", self.gender];
return desc
}
...
...
#end

Related

How can I customize the NSdictionary using Mantle?

I have the following json string:
{"suit_id": 2427;
"suits": "http://img.prettyyes.com/1137-4930-1446175512.jpeg;http://img.prettyyes.com/1137-7665-1446175512.jpeg;http://img.prettyyes.com/1137-4783-1446175512.jpeg"}
So when use mantle to parse the json string with following file
testModel.h
#interface testModel : MTLModel <MTLJSONSerializing>
#property (nonatomic, strong) NSString *suit_id;
#property (nonatomic, strong) NSString *suits;
#end
testModel.m
#implementation testModel
+ (NSDictionary *) JSONKeyPathsByPropertyKey {
return #{
"suit_id": "suit_id",
"suits": "suits"
};
}
#end
How ever I would like to convert suits from string to a NSArray with multiple urls so I did following:
testModel.h
#interface testModel : MTLModel <MTLJSONSerializing>
#property (nonatomic, strong) NSString *suit_id;
#property (nonatomic, strong) NSArray *suits;
#end
testModel.m
#implementation testModel
+ (NSDictionary *) JSONKeyPathsByPropertyKey {
return #{
"suit_id": "suit_id",
"suits": "suits"
};
}
+ (NSValueTransformer *) suitsJSONTransform {
return [MTLValueTransformer transformerUsingForwardBlock:^(NSString *str, BOOL *success, NSError **error){
return [[str componentsSeparatedByString:#";"] mutableCopy];
}];
}
#end
But it's not working. The result is nil. When I override the wrong function?
The method returning the NSValueTransformer for suits should be called suitsJSONTransformer, not suitsJSONTransform.
The format for the method name is <propertyName>JSONTransformer.

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];
}

Creating Dictionary from a model that contains nil values

I have the following Model:
#interface Person : NSObject
#property (nonatomic, copy) NSString *firstName;
#property (nonatomic, copy) NSString *middleName;
#property (nonatomic, copy) NSString *lastName;
#property (nonatomic, copy) NSString *status;
#property (nonatomic, copy) NSString *favoriteMeal;
#property (nonatomic, copy) NSString *favoriteDrink;
#property (nonatomic, copy) NSString *favoriteShow;
#property (nonatomic, copy) NSString *favoriteMovie;
#property (nonatomic, copy) NSString *favoriteSport;
-(NSDictionary *)getSomeInfo;
-(NSDictionary *)getAllInfo;
#end
Part 1:
I want getSomeInfo to return NSDictionary (e.g. {"firstName", self.firstName}) for all the fields that does not contain nil. How can I do that? (I could check every value but I wonder if there's a better way)
Part 2:
I want getAllInfo to return NSDictionary with all the property and if one contains nil then it should throw an error. Again do I have to write a long conditional statement to check or is there a better way?
Note: I want to do this without using external library. I'm new to the language so I'm open to suggestions if there's a better pattern in Objective-C.
There are two approaches.
1) Check each value:
- (NSDictionary *)getSomeInfo {
NSMutableDictionary *res = [NSMutableDictionary dictionary];
if (self.firstName.length) {
res[#"firstName"] = self.firstName;
}
if (self.middleName.length) {
res[#"middleName"] = self.middleName;
}
// Repeat for all of the properties
return res;
}
2) Use KVC (Key-value coding):
- (NSDictionary *)getSomeInfo {
NSMutableDictionary *res = [NSMutableDictionary dictionary];
NSArray *properties = #[ #"firstName", #"middleName", #"lastName", ... ]; // list all of the properties
for (NSString *property in properties) {
NSString *value = [self valueForKey:property];
if (value.length) {
res[property] = value;
}
}
return res;
}
For the getAllInfo method you can do the same but instead return nil if any value is missing. Treat the nil results as your indication that not all properties have a value.

Store scalar values (NSInteger, BOOL, double) in CoreData without converting to NSNumber

I have read a lot of articles where they say to explicitely convert from and to NSNumber when I want to store scalars in CoreData:
#property (nonatomic, assign) NSInteger value;
- (NSInteger)value
{
return [value integerValue];
}
- (void)setValue:(NSInteger)val
{
value = [NSNumber numberWithInteger:val];
}
But in our old project we have a bunch of properties where we doesn't do those manipulations (and they don't have custom accessors)! Why it works?
Example code
Declaration. Scalar values are not transient.
#interface ProductProperty : NSManagedObject
#property (nonatomic, strong, readonly) NSString * propertyID;
#property (nonatomic, strong, readonly) NSString * title;
#property (nonatomic, strong, readonly) NSSet * values;
#property (nonatomic, assign, readonly) BOOL filter;
#property (nonatomic, strong, readonly) NSDate *update;
#property (nonatomic, strong, readonly) NSNumber *index;
#property (nonatomic, assign, readonly) BOOL system;
#end
#import "ProductProperty.h"
#implementation ProductProperty
#dynamic propertyID;
#dynamic title;
#dynamic values;
#dynamic filter;
#dynamic update;
#dynamic index;
#dynamic system;
#end
Mapping into objects. Called if received JSON differs from existing. Otherwise it fetches from the CoreData storage.
- (void)updateProperties:(NSArray*)properties
{
for (NSDictionary *_property in properties) {
NSString *propertyID = [_property objectForKey:#"id"];
ProductProperty *property = [state.productPropertiesWithIDs objectForKey:propertyID];
if (!property) {
property = [state.ctx newObjectWithEntityName:ProductProperty.entityName];
property.propertyID = propertyID;
[state.productPropertiesWithIDs setObject:property forKey:propertyID];
}
property.update = state.update;
property.title = [_property objectForKey:#"title"];
property.filter = [_property objectForKey:#"filter"] ? [[_property objectForKey:#"filter"] boolValue] : YES;
property.index = [propertyIndexes objectForKey:propertyID] ? [propertyIndexes objectForKey:propertyID] : [NSNumber numberWithInt:propertyIndex++];
property.system = [SYSTEM_PROPERTY_IDS containsObject:propertyID] ? YES : NO;
[self updatePropertyValues:[_property objectForKey:#"values"] forProperty:property];
}
}
- (ProductProperty*)productPropertyWithID:(NSString*)propertyId error:(NSError**)error
{
NSFetchRequest *req = [ProductProperty request];
req.predicate = [NSPredicate predicateWithFormat:#"propertyID == %#", propertyId];
return [[ctx executeFetchRequest:req error:error] lastObject];
}
The answer is that since iOS 5 CoreData support auto generating accessors for scalars so I don't need to implement them manually.