开发者

Objective-C for Dummies: How do I loop through an NSDictionary inside of an NSDictionary?

开发者 https://www.devze.com 2023-02-09 08:10 出处:网络
Alright guys, I\'m quite confused. So, I have an NSDictionary which is populated by a JSON string which looks like:

Alright guys, I'm quite confused. So, I have an NSDictionary which is populated by a JSON string which looks like:

{"Success":true,"Devices":[{"UDId":"...","User":"...","Latitude":0.0,"Longitude":0.0}]}

Now, I know how to check if Success is true, but I need to loop through the array of Devices (JSON object) and create an internal array of Devices (internal app object) and I have no idea how to do that. Can someone please explain how to do it?

Here's my Device.m/h:

#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>

@interface Device : NSObject {
    NSString *udId;
    NSString *name;
    NSNumber *latitude;
    NSNumber *longitude;
}

@property (nonatomic, retain) NSString *udId;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSNumber *latitude;
@property (nonatomic, retain) NSNumber *longitude;

#pragma mark -
#pragma mark MKAnnotation Properties
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@end

----

#import "Device.h"

@implementation Device

@synthesize udId, name, latitude, longitude;

- (CLLocationCo开发者_StackOverflow中文版ordinate2D)coordinate {
    CLLocationCoordinate2D internalCoordinate;

    internalCoordinate.latitude = [self.latitude doubleValue];
    internalCoordinate.longitude = [self.longitude doubleValue];

    return internalCoordinate;
}

- (void)dealloc {
    [udId release];
    udId = nil;

    [name release];
    name = nil;

    [latitude release];
    latitude = nil;

    [longitude release];
    longitude = nil;

    [super dealloc];
}

@end

And here's the methods where I should be reading the response and converting it to objects I can use:

- (void)requestFinished:(ASIHTTPRequest *)request {
    if (![request error]) {
        NSError *jsonError = nil;
        NSDictionary *jsonDictionary = [NSDictionary dictionaryWithJSONString:[request responseString] error:&jsonError];

        if (!jsonError || ([[jsonDictionary objectForKey:@"Success"] intValue] == 1)) {
            //  READ "DEVICES" AND CONVERT TO OBJECTS
        } else {
            //  AUTHORIZATION FAILED
        }
    }
}

I'd really appreciate some help on this. I just can't seem to wrap my head around it...

Thanks in advance!


You are almost there. In your code where you say:

  //  READ "DEVICES" AND CONVERT TO OBJECTS

do this:

  NSArray * devices = [jsonDictionary objectForKey:@"Devices"];
  for(NSDictionary * deviceInfo in devices) {
    Device * d = [[[Device alloc] init] autorelease];
    [d setLatitude:[deviceInfo objectForKey:@"Latitude"]];
    [d setLongitude:[deviceInfo objectForKey:@"Longitude"]];
    [d setName:[deviceInfo objectForKey:@"User"]];
    [d setUdId:[deviceInfo objectForKey:@"UDId"]];
    // do some stuff with d
  }

What's going on here: I didn't see what JSON library you are using to convert, but presuming it works like TouchJSON or SBJSON, the JSON array is automatically turned into an NSArray instance, while the inner hashes of the NSArray are NSDictionary objects. At the point that you have deserialized that JSON string, everything you're dealing with will be instances of NSString, NSNumber, NSArray and NSDictionary (and depending on the library, NSNull to represent null values).


First you need to define your initializer/constructor for your Device class.

Device.h

- (id)initWithUdid:(NSString *)udid name:(NSString *)name latitude:(NSNumber *)lat longitude:(NSNumber *)lon;

Device.m

- (id)initWithUdid:(NSString *)udid name:(NSString *)name latitude:(NSNumber *)lat longitude:(NSNumber *)lon {
    if (self = [super init]) {
        self.udid = udid;
        self.name = name;
        self.latitude = lat;
        self.longitude = lon;
    }
    return self;
}

Then you can initialize a new object like:

Device *dev = [[Device alloc] initWithUdid:@"a udid" name:@"the name" latitude:latNum longitude:lonNum];

So, you should be able to iterate the array and build your Device objects like so:

NSArray *devicesArray = [dict objectForKey:@"Devices"];
for (NSDictionary *d in devicesArray) {
  Device *dev = [[Device alloc] initWithUdid:[d objectForKey:@"UDId"]
                                        name:[d objectForKey:@"User"]
                                    latitude:[NSNumber numberWithDouble:[d objectForKey:@"Latitude"]]
                                   longitude:[NSNumber numberWithDouble:[d objectForKey:@"Latitude"]]];
}


You want to access the array of device dictionaries from the top-level dictionary just as you did the Success value. Then iterating over the dictionaries you can use each's -keyEnumerator method to iterate over its keys.

- (void)requestFinished:(ASIHTTPRequest *)request {
    if (![request error]) {
        NSError *jsonError = nil;
        NSDictionary *jsonDictionary = [NSDictionary dictionaryWithJSONString:[request responseString] error:&jsonError];

        if (!jsonError || ([[jsonDictionary objectForKey:@"Success"] intValue] == 1)) {
            NSArray* deviceArray = [jsonDictionary objectForKey:@"Devices"];
            for(NSDictionary* dict in deviceArray)
            {
                for(NSString* key in [dict keyEnumerator])
                {
                    NSLog(@"%@ -> %@", key, [dict objectForKey:key]);
                }
            }
            //  READ "DEVICES" AND CONVERT TO OBJECTS
        } else {
            //  AUTHORIZATION FAILED
        }
    }
}


Sounds like you need to reuse your line:

[jsonDictionary objectForKey:@"Success"]

try having a look at

[jsonDictionary objectForKey:@"Devices"]

You really need to figure out what type it returns. If you're lucky, it returns an NSDictionary, or alternately something that you can easily turn into an NSDictionary.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号