I have a json string:
{"1":{"homeTeam":"Home01","awayTeam":"Away01","homeScore":0,"awayScore":0,"gameID":1},"2":{"homeTeam":"Home11","awayTeam":"Away11","homeScore":0,"awayScore":0,"gameID":2},"3":{"homeTeam":"Home21","awayTeam":"Away21","homeScore":0,"awayScore":0,"gameID":3}}
that I would like to turn into an Objective-C class:
#import <Foundation/Foundation.h>
#interface ScoreKeeperGame : NSObject {
}
#property (nonatomic, retain) NSString *homeTeam;
#property (nonatomic, retain) NSString *awayTeam;
#property (nonatomic, assign) int homeScore;
#property (nonatomic, assign) int awayScore;
#property (nonatomic, assign) int gameID;
- (id) init: (NSString *) homeTeam
awayTeam: (NSString *) awayTeam;
- (id) init: (NSDictionary *) game;
#end
I pass the json in by NSDictionary "game" (the json string represents a hashmap, so the first game is):
{"homeTeam":"Home01","awayTeam":"Away01","homeScore":0,"awayScore":0,"gameID":1}
When I try to use this class:
#import "ScoreKeeperGame.h"
#implementation ScoreKeeperGame
#synthesize homeTeam=_homeTeam, awayTeam = _awayTeam, homeScore = _homeScore, awayScore = _awayScore, gameID = _gameID;
- (id) init: (NSString *) homeTeam
awayTeam: (NSString *) awayTeam
{
self = [super init];
self.homeTeam = homeTeam;
self.awayTeam = awayTeam;
NSLog(#"away: %#", awayTeam);
return self;
}
- (id) init: (NSDictionary *) game
{
self = [super init];
if(self)
{
self.homeTeam = [game objectForKey:#"homeTeam"];
self.awayTeam = [game objectForKey:#"awayTeam"];
self.awayScore = (int) [game objectForKey:#"awayScore"];
self.gameID = [game objectForKey:#"gameID"];
NSLog(#"game awayScore: %d", self.awayScore);
NSLog(#"game gameID: %#", [NSNumber numberWithInt:self.gameID]);
}
return self;
}
#end
The awayScore and gameId are printed as large numbers (maybe pointers)?
I've tried
self.awayScore = [NSNumber numberWithInt: [game objectForKey:#"awayScore"]];
But that didn't seem to work either.
How do I get the value of the int from the game object?
po game produces:
{
awayScore = 0;
awayTeam = Away01;
gameID = 1;
homeScore = 0;
homeTeam = Home01;
}
Thanks!
You have to pull it out as an NSNumber first.
NSNumber *myNum = [game objectForKey:#"awayScore"];
self.awayScore = [myNum intValue];
Doh!
you can try this if you want to get integer value from your JSON response
self.awayScore = [NSNumber numberWithInt: [[game objectForKey:#"awayScore"] intValue]];
as your response would be in nsstring.
iOs 6.0, now it's simply [game[#"awayScore"] intValue]
Related
First off, I come from Lua, don't blame me for being global variable minded lol. So, I've been reading up on how to use this whole "Singleton system" and I'm not sure if I'm completely missing the point or if I'm just implementing it incorrectly?
The goal of my code is to create a way for multiple files to access a variable that holds the size of an array in a specific file. Here is my singleton:
.h
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject
{
NSNumber *currentGameArrayCount;
BOOL *isGamePaused;
}
#property (nonatomic, readwrite) NSNumber *currentGameArrayCount;
#property (nonatomic, readwrite) BOOL *isGamePaused;
+ (GlobalVariables *)sharedInstance;
#end
.m
#import "GlobalVariables.h"
#implementation GlobalVariables
#synthesize currentGameArrayCount, isGamePaused;
static GlobalVariables *gVariable;
+ (GlobalVariables *)sharedInstance
{
if (gVariable == nil) {
gVariable = [[super allocWithZone:NULL] init];
}
return gVariable;
}
- (id)init
{
self = [super init];
if (self)
{
currentGameArrayCount = [[NSNumber alloc] initWithInt:0];
isGamePaused = NO;
}
return self;
}
#end
and in another file with the array I use:
GlobalVariables *sharedData = [GlobalVariables sharedInstance];
NSNumber *tmpArrayCount = [sharedData currentGameArrayCount];
NSInteger tmpCount = [whereStuffActuallyHappens.subviews count]; // Subviews is the array
NSNumber *currentCount = [NSNumber numberWithInteger:tmpCount];
tmpArrayCount = currentCount;
the hope of this code was to get the variable in the singeton (currentGameArrayCount) and set it too what the current array count was (currentCount). Am I incorrectly interpreting the purpose of a singleton? Am I just bad at singletons and didn't set it up correctly? Does anyone know how I could achieve the result of getting my array count to be accesible to all my files?
You have a few issues. Try these changes:
GlobalVariables.h:
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject
#property (nonatomic, assign) int currentGameArrayCount;
#property (nonatomic, assign) BOOL gamePaused;
+ (GlobalVariables *)sharedInstance;
#end
GlobalVariables.m:
#import "GlobalVariables.h"
static GlobalVariables *gVariable = nil;
#implementation GlobalVariables
+ (GlobalVariables *)sharedInstance {
if (gVariable == nil) {
gVariable = [[self alloc] init];
}
return gVariable;
}
- (id)init {
self = [super init];
if (self) {
self.currentGameArrayCount = 0;
self.gamePaused = NO;
}
return self;
}
#end
Now in your other code you can do:
GlobalVariables *sharedData = [GlobalVariables sharedInstance];
int tmpArrayCount = sharedData.currentGameArrayCount;
NSInteger tmpCount = [whereStuffActuallyHappens.subviews count]; // Subviews is the array
sharedData.currentGameArrayCount = tmpCount;
I want to serialize array to JSON.
Here is my JSON -
{
"User":{"Id":"1222","Email":"asdad#adasd.com"},
"Person":{"Name":"John","Surname":"Smith"}
}
values 1222, asdad#adasd.com, John, Smith are examples. this values will be define in controller.
I don't know how to handle serialize this arrays inside JSON.
I need to send objects - user and person to the server with different values, depending on the user. This is my model. Both are arrays.
Here is my code
Header
#import <Foundation/Foundation.h>
#import "BaseRequest.h"
#interface SaveUserProfileRequest : BaseRequest {
NSMutableArray *_user;
NSMutableArray *_person;
NSMutableArray *_address;
NSString *_userId;
NSString *_userEmail;
NSString *_userName;
NSString *_userSurname;
}
- (id)initWithUser:(NSMutableArray*)user andPerson:(NSMutableArray*)person andAddress:(NSMutableArray*)address andUserId:(NSString*)userId andUserEmail:(NSString*)userEmail andUserName:(NSString*)userName andUserSurname:(NSString*)userSurname;
#property (nonatomic, strong) NSMutableArray* user;
#property (nonatomic, strong) NSMutableArray* person;
#property (nonatomic, strong) NSMutableArray* address;
#property (nonatomic, strong) NSString* userId;
#property (nonatomic, strong) NSString* userEmail;
#property (nonatomic, strong) NSString* userName;
#property (nonatomic, strong) NSString* userSurname;
#end
Implementation
#import "SaveUserProfileRequest.h"
#import "SaveUserProfileResponse.h"
#import "OrderedDictionary.h"
#import "BaseData.h"
#implementation SaveUserProfileRequest
#synthesize user=_user, person=_person, address=_address, userId=_userId, userEmail=_userEmail, userName=_userName, userSurname=_userSurname;
- (id)initWithUser:(NSMutableArray*)user andPerson:(NSMutableArray*)person andAddress:(NSMutableArray*)address andUserId:(NSString*)userId andUserEmail:(NSString*)userEmail andUserName:(NSString*)userName andUserSurname:(NSString*)userSurname; {
self = [super init];
if(self){
self.user = user;
self.person = person;
self.address = address;
self.userId = userId;
self.userEmail = userEmail;
self.userName = userName;
self.userSurname = userSurname;
}
return self;
}
- (NSDictionary*) serialize{
OrderedDictionary *sup = [OrderedDictionary dictionaryWithCapacity:3];
[sup setValue:self.user forKey:#"User"];
[sup setValue:self.person forKey:#"Person"];
NSArray *users = [OrderedDictionary valueForKey:#"User"];
_user = [NSMutableArray arrayWithCapacity:[users count]];
for(NSDictionary *user in users){
OrderedDictionary *userDict = [OrderedDictionary dictionaryWithCapacity:2];
[userDict setValue:self.userId forKey:#"Id"];
[userDict setValue:self.userEmail forKey:#"Mail"];
return userDict;
}
NSArray *persons = [OrderedDictionary valueForKey:#"Person"];
_person = [NSMutableArray arrayWithCapacity:[persons count]];
for(NSDictionary *person in persons){
OrderedDictionary *personsDict = [OrderedDictionary dictionaryWithCapacity:2];
[personsDict setValue:self.userName forKey:#"Name"];
[personsDict setValue:self.userSurname forKey:#"Surname"];
return personsDict;
}
return sup;
}
Please, help me a little
Every little hint will be really appreciate.
Thanks !
For handeling JSON in Objective-C, I always use JSONKit. You can fork it here: https://github.com/johnezang/JSONKit
Some examples on how it can be used:
NSArray *array = #[..];
NSString *arrayAsJsonString = [array JSONString];
NSString *string = #"..";
id objectFromJsonString = [string objectFromJSONString]; // i.e an NSArray or NSDictionary
If your app is for iOS 5 or greater, you can use NSJSONSerialization:
http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html
Otherwise I recommend SBJson.
I know this can be done with many languages, but I don't see how to do it using Objective-C. I've read about singletons but as they are designed to be instanciated only once, they do not feed this need.
So this class could be called like this :
MyClass* obj1 = [[MyClass alloc] initWithKey:#"oneKey"];
NSString* lib = obj1.lib;
or
int id = [MyClass idForKey:#"anotherKey"];
I've tried this code but I'm pretty sure it's really bad, but I don't see how to achieve this :
.h file
#interface MyClass : NSObject {
NSString* key;
}
#property(nonatomic, retain) NSString* key;
#property(nonatomic, readonly) int id;
#property(nonatomic, readonly) NSString* lib;
#property(nonatomic, readonly) int value;
+ (id) classWithKey:(NSString*)theKey;
#end
.m file
#import "MyClass.h"
#interface MyClass.h (Private)
-(id)initWithKey:(NSString*)theKey;
#end
#implementation MyClass
#synthesize key;
static NSMutableDictionary* vars = nil;
-(id)init
{
if (!(self = [super init])) return nil;
self.key = nil;
[MyClass initVars];
return self;
}
-(id)initWithKey:(NSString*)theKey
{
if (!(self = [super init])) return nil;
self.key = theKey;
[MyClass initVars];
return self;
}
+ (id) classWithKey:(NSString*) theKey
{
return [[[MyClass alloc] initWithKey:theKey] autorelease];
}
+(void)initVars
{
if (vars != nil) return;
#define mNum(x) [NSNumber numberWithInt:x]
#define k0 #"id"
#define k1 #"lib"
#define k2 #"val"
vars = [NSMutableDictionary dictionary];
[vars setObject:[NSDictionary dictionaryWithObjectsAndKeys:mNum(5), k0, #"One value", k1, mNum(0), k2, nil] forKey:#"oneKey"];
[vars setObject:[NSDictionary dictionaryWithObjectsAndKeys:mNum(8), k0, #"Another value", k1, mNum(1), k2, nil] forKey:#"anotherKey"];
...
[vars retain];
}
- (int)id { return [[[vars objectForKey:self.key] objectForKey:k0] intValue]; }
- (NSString*)lib { return [[vars objectForKey:self.key] objectForKey:k1]; }
- (int)value { return [[[vars objectForKey:self.key] objectForKey:k2] intValue]; }
-(void)dealloc
{
self.key = nil;
[vars release];
[super dealloc];
}
+(int) idForKey:(NSString*)theKey
{
if (vars == nil) [self initVars];
return [[[vars objectForKey: theKey] objectForKey:k0] intValue];
}
#end
take a look at singleton class concept
there are a lot of answer for singletons, just search
here's' one:
Is this really a singleton?
I've made a container class to store a single tweet. Its initialized by passing in a dictionary object which is a single tweet.
I then store an array of these 'tweets' which I process through to display in a table.
The project is now finished and I am reviewing everything at the moment and I was wondering is there a better way to do this in the future. Is the memory handled correctly. I declare the string member vars with 'copy' and later in the dealloc I use a 'release' rather than just setting them to 'nil'.
Is my init ok or could that be improved?
Tweet.h
#import
#interface Tweet : NSObject
{
NSString * _userName;
NSString * _tweetText;
NSString * _tweetURL;
}
#property (nonatomic, copy) NSString * userName;
#property (nonatomic, copy) NSString * tweetText;
#property (nonatomic, copy) NSString * tweetURL;
- (id) initWithDict:(NSDictionary *)productsDictionary;
#end
Tweet.m
#implementation Tweet
#synthesize userName = _userName;
#synthesize tweetText = _tweetText;
#synthesize tweetURL = _tweetURL;
- (id) initWithDict:(NSDictionary *)productsDictionary
{
NSDictionary *aDict = [productsDictionary objectForKey:#"user"];
self.userName = [aDict objectForKey:#"screen_name"];
self.tweetText = [productsDictionary objectForKey:#"text"];
NSRange match;
match = [self.tweetText rangeOfString: #"http://"];
if (match.location != NSNotFound)
{
NSString *substring = [self.tweetText substringFromIndex:match.location];
NSRange match2 = [substring rangeOfString: #" "];
if (match2.location == NSNotFound)
{
self.tweetURL = substring;
}
else
{
self.tweetURL = [substring substringToIndex:match2.location];
}
}
else
{
self.tweetURL = nil;
}
return self;
}
-(void) dealloc
{
[self.tweetText release];
[self.tweetURL release];
[self.userName release];
[super dealloc];
}
#end
Many Thanks,
Code
At first sight, I see no inherent flaws here. That looks fine. I would prefer to do:
-(void) dealloc
{
[_tweetText release];
[_tweetURL release];
[_userName release];
[super dealloc];
}
But what you do is good as well.
So in my model I have the following code... I am successfully able to return each individual value. I want to know how am I able to return the entire speakerTable []... Maybe some advice. Thanks!
typedef struct {
NSUInteger speakerID;
NSString * speakerName;
NSString * speakerPosition;
NSString * speakerCompany;
} SpeakerEntry;
static const SpeakerEntry speakerTable [] =
{
{0, #"name", #"position", #"company"},
{1, #"name", #"position", #"company"},
{-1, nil, nil, nil}
};
This works correctly...
-(NSString *) stringSpeakerCompanyForId:(NSUInteger) identifier{
NSString * returnString = nil;
if ([self helpCount] > identifier) {
returnString = speakerTable[identifier].speakerCompany;
}
return returnString;
}
This does not work at all..
-(id) getSpeaker{
//if ([speakerTable[0].speakerName isKindOfClass:[NSString class]])
// NSLog(#"YES");
NSArray * myArray3 = [NSArray arrayWithArray:speakerTable];
return myArray3;
}
arrayWithArray expects an NSArray, not a C array.
The first one works because you are using it like a C array.
Alternatively - don't use a struct, use an object instead:
Create a class called Speaker.
In Speaker.h
#interface Speaker : NSObject {}
#property (nonatomic, assign) NSUinteger id;
#property (nonatomic, copy) NSString name;
#property (nonatomic, copy) NSString position;
#property (nonatomic, copy) NSString company;
- (void)initWithId:(NSUInteger)anId name:(NSString *)aName position:(NSString *)aPosition company:(NSString *)aCompany;
#end
in Speaker.m
#import "Speaker.h"
#implementation Speaker
#synthesize id, name, position, company;
- (void)initWithId:(NSUInteger)anId name:(NSString *)aName position:(NSString *)aPosition company:(NSString *)aCompany {
if (!([super init])) {
return nil;
}
id = anId;
NSString name = [[NSString alloc] initWithString:aName];
NSString position = [[NSString alloc] initWithString:aPosition];
NSString company = [[NSString alloc] initWithString:aCompany];
return self;
}
- (void)dealloc {
[name release];
[position release];
[company release];
[super dealloc];
}
#end
And now in your calling code you can create an immutable array of speakers with:
Speaker *speaker0 = [[Speaker alloc] initWithId:0 name:#"name0" position:#"position0" company:#"company0"];
Speaker *speaker1 = [[Speaker alloc] initWithId:1 name:#"name1" position:#"position1" company:#"company1"];
Speaker *speakerNull = [[Speaker alloc] initWithId:-1 name:nil position:nil company:nil];
NSArray *speakerArray [[NSArray arrayWithObjects: speaker0, speaker1, speakerNull] retain]
[speaker0 release];
[speaker1 release];
[speakerNull release];
note: this is typed straight in, so feel free to mention/correct typos or errors
The method arrayWithArray takes in an NSArray as an argument, not a C array.