How to create json like structure in Objective C in class property? - ios

I am having the view controller class like this
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic, strong) NSDictionary *dictionary;
#end
ViewController.m
#import "ViewController.h"
#import "GoogleMaps.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//HOW TO ACCESS THE PROPERTY VALUE HERE
self.dictionary = #{};
/ DUMP ALL FOUND ITEMS
for(DummyContainer* geoItem in geoItems) {
NSDictionary *item = #{
#"latitude":geoItem.latitude,
#"longtitude":geoItem.longtitude
};
self.dictionary[geoItem.geoPoint.name] = item;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The expected format is
var container = {
'location':{
'latitude':1233,
'longtitude':124
}
}
This can be accessible via
let obj = container['location'];
for latitude access like this
obj.latitude;
Question1: How to create a class property as dictionary and access inside the class?
Question2: How to create JSON structure and access the values?
I am new to iOS please help me thanks in advance.

For creating non extendable/immutable Dictionary Object
#property (strong, nonatomic) NSDictionary *myClassDictionary;
For creating extendable/mutable Dictionary Object
#property (strong, nonatomic) NSMutableDictionary *myClassMutableDictionary;
Insert all of your values inside a Dictionary like this
You exampleData
'location':{
'latitude':1233,
'longtitude':124
}
NSDictionary *dict = #{#"lattitude":#"1233" , #"longitude":#"124"};
self.myClassDictionary = #{#"location":dict};//Convert this dictionary into JSON.
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: self.myClassDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString jsonString;
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

Related

My application crashes with this error - 'NSInvalidArgumentException'

I have created a program to retrieve JSON file and it achieved it
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Your Json Dictionary values are %#", jsonDict);
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]integerValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]integerValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
But My app crashes here with the above error
[self.objectForArray addObject:shopObject];
}
}
Updated my shop collection code below
Shopcollection object.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#property(nonatomic, strong)NSString* Name;
#property (nonatomic) int TimeAsPrice;
#property (nonatomic,strong) NSString* Avathar;
#property (nonatomic,strong) NSString* user;
#property (nonatomic,strong) NSString* Name_User;
#property(nonatomic,strong) NSString* LocationOfUser;
#end
Shopcollectionobject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
You likely aren't initializing your objectForArray. So when you try to call addObject, it's calling it on a null object.
ShopCollectionObject.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
#property (nonatomic) int message_id;
#property (strong, nonatomic) NSString *Name;
#property (nonatomic) int TimeAsPrice;
#property (strong, nonatomic) NSString *Avathar;//user,Name_User,LocationOfUser,message_id
#property (strong, nonatomic) NSString *user;
#property (strong, nonatomic) NSString *Name_User;
#property (strong, nonatomic) NSString *LocationOfUser;
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#end
ShopCollectionObject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
ViewController.m
#import "ViewController.h"
#import "ShopCollectionObject.h"
#interface ViewController ()
{
NSMutableArray *objectForArray;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
objectForArray = [[NSMutableArray alloc]init];
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]intValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]intValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
[objectForArray addObject:shopObject];
}
NSLog(#"%#",objectForArray);
ShopCollectionObject *data = objectForArray[0];
NSLog(#"%#",data.Name);
}
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
pls check this code

Save NSMutableArray of NSStrings to disk

I have a NSMutableaArray of NSString objects. So i'm using NSKeyedArchiever to save it to disk. So when i try to use
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
i got an error
Event encodeWithCoder:]: unrecognized selector sent to instance 0x7fd06b542780
Here's my parts of code:
//-------------------Events.h--------------------------
#interface Event : NSObject
#property (strong,nonatomic) NSString *nameOfEvent;
#property (strong,nonatomic) NSString *dateOfEvent;
#property (strong,nonatomic) NSString *placeOfEvent;
#property int priorityOfEvent;
#end
//---------------Singleton.h ----------------
#interface GlobalSingleton : NSObject <NSCoding, NSCopying> {
NSMutableArray *EventsList;
}
#property (nonatomic,retain) NSMutableArray *EventsList;
+(GlobalSingleton *)sharedFavoritesSingleton;
#end
//----------------Singleton.m------------------------
....
#implementation GlobalSingleton
#synthesize EventsList;
....
....
- (void)encodeWithCoder:(NSCoder *)aCoder {
NSLog (#"%#",EventsList); // not nil
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super init])) {
NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:[aDecoder decodeObjectForKey:#"Events"]];
self.EventsList = temp;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
GlobalSingleton *copy = [[GlobalSingleton allocWithZone:zone] init];
copy.EventsList = self.EventsList;
return copy;
}
#end
I get textdata from Web-server using ASIFormDataRequest in JSON format, and then i add this object to NSMutableArray, which is also a Singleton, so it looks like this:
NSDictionary *responseDict = [responseString JSONValue];
GlobalSingleton *Singleton = [GlobalSingleton sharedFavoritesSingleton];
for (NSDictionary *str in responseDict) {
Event *newEvent = [[Event alloc] init];
newEvent.nameOfEvent = [str objectForKey:#"EventName"];
newEvent.dateOfEvent = [str objectForKey:#"EventDate"];
newEvent.placeOfEvent = [str objectForKey:#"EventPlace"];
[Singleton.EventsList addObject:newEvent];
}
//------------------Save this data stored in NSMutableArray to disk-------------------------
[NSKeyedArchiver archiveRootObject:Singleton toFile:[self save_path]];
So, again, execution stops on this:
[aCoder encodeObject:self.EventsList forKey:#"Events"];
But when i try to code single NSString object everything goes with no errors.
eventList doesn't contain NSStrings, it contains Event objects.
Your Event class needs to implement encodeWithCoder: - as the exception message says, the Event class doesn't implement this method.
Also you should use a lowercase s for singleton as it is an instance, not a class, and you should probably not use singletons.

Trouble setting an NSMutableDictionary inside of another NSMutableDictionary

I need to take information submitted by a user, store that information in an NSMutableDictionary, then store that NSMutableDictionary inside another NSMutableDictionary which is then encoded inside another class. For whatever reason, I can't seem to store the first NSMutableDictionary inside of the other.
I had to slim down the code that's in here due to work rules, so sorry if it seems to be missing anything. I only posted the parts that I'm having trouble with.
UserInfo.h:
#import <Foundation/Foundation.h>
#interface MyPlanInfo : NSObject <NSCoding>
#property (nonatomic, strong) NSMutableDictionary *emergencyDictionary;
#end
UserInfo.m:
#import <Foundation/Foundation.h>
#import "MyPlanInfo.h"
static NSString *emergencyDictionaryKey = #"emergencyDictionaryKey";
#implementation MyPlanInfo
#synthesize emergencyDictionary;
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.emergencyDictionary forKey:emergencyDictionaryKey];
}
#end
infoView.h
#import <UIKit/UIKit.h>
#import "MyPlanInfo.h"
#interface infoView : UIViewController <NSCoding>
{
NSMutableDictionary *emergencyContactInfo;
NSArray *userInfo;
NSArray *userKeys;
NSMutableArray *tempArray;
}
#property (nonatomic, strong) MyPlanInfo *myPlanInfoObject;
-(void)saveUserInfo;
-(void)loadUserInfo;
#end
infoView.m:
#import "infoView.h"
#interface infoView ()
#end
#implementation infoView
static NSString *userInfoKey = #"userInfoKey";
static NSString *userName;
-(void)viewDidLoad
{
[super viewDidLoad];
if(!self.myPlanInfoObject)
{
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
}
[self loadUserInfo];
}
-(void)addToDictionary
{
emergencyContactInfo = [NSMutableDictionary dictionaryWithObjects:userInfo forKeys:userKeys];
if([userInfo count] != 0 || userInfo == nil)
{
self.myPlanInfoObject.emergencyDictionary = [NSMutableDictionary dictionaryWithObject:emergencyContactInfo forKey:userName];
}
[self saveUserInfo];
}
- (void)saveUserInfo
{
NSData *userInfoData = [NSKeyedArchiver archivedDataWithRootObject:self.myPlanInfoObject];
[[NSUserDefaults standardUserDefaults] setObject:userInfoData forKey:userInfoKey];
}
- (void)loadUserInfo
{
NSData *userInfoData = [[NSUserDefaults standardUserDefaults] objectForKey:userInfoKey];
if(userInfoData)
{
self.myPlanInfoObject = [NSKeyedUnarchiver unarchiveObjectWithData:userInfoData];
}
}
#end
In infoView.m, in the addToDictionary method, userInfo is an array of user inputted information, and userKey's is an array of key's. The emergencyContactInfo NSMutableDictionary works just fine, everything is in it, but when I try to set that as an object in a new NSMutableDictionary, for a key, it doesn't work. Everything is nil.
Anyone have any ideas on how what I'm doing wrong?
Edit: If you down vote, please leave a reason as to why so that I can avoid doing whatever I did wrong in the future.
In the following line you’re creating an instance of MyPlanInfo using plain alloc/init:
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
However, at least in the code provided, you haven’t overridden init in MyPlanInfo, but instead, initWithCoder::
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
When you use just plain init, the MyPlanInfo’s emergencyDictionary instance variable will be nil. You should likely add something like the following to MyPlanInfo to override init:
- (id) init
{
if ((self = [super init])) {
emergencyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
That will assure that the newly created MyPlanInfo instance has a proper NSMutableDictionary that can be manipulated from other classes.

Reference NSManagedObject entity from inside NSValueTransformer

I'm using NSValueTranformer to encrypt certain Core Data attributes. This all works fine, except I need to be able to use a different encryption key depending on the NSManagedObject. Is there anyway I can access this entity from within my transformer class?
The use case is I have multiple users with different passwords that can access different NSManagedObject entities. If I use the same encryption key for all of the objects, someone could just reassign who owns them in the SQL db and they would still decrypt.
Any ideas on the best way to go about this?
Edit:
I should mention I'm doing this in iOS.
Third times the charm? Let me see if I can address your only-transform-when-going-to-disk requirement. Think of this as a hybrid of the other two approaches.
#interface UserSession : NSObject
+ (UserSession*)currentSession;
+ (void)setCurrentSession: (UserSession*)session;
- (id)initWithUserName: (NSString*)username andEncryptionKey: (NSData*)key;
#property (nonatomic, readonly) NSString* userName;
#property (nonatomic, readonly) NSData* encryptionKey;
#end
#implementation UserSession
static UserSession* gCurrentSession = nil;
+ (UserSession*)currentSession
{
#synchronized(self)
{
return gCurrentSession;
}
}
+ (void)setCurrentSession: (UserSession*)userSession
{
#synchronized(self)
{
gCurrentSession = userSession;
}
}
- (id)initWithUserName: (NSString*)username andEncryptionKey: (NSData*)key
{
if (self = [super init])
{
_userName = [username copy];
_encryptionKey = [key copy];
}
return self;
}
- (void)dealloc
{
_userName = nil;
_encryptionKey = nil;
}
#end
#interface EncryptingValueTransformer : NSValueTransformer
#end
#implementation EncryptingValueTransformer
- (id)transformedValue:(id)value
{
UserSession* session = [UserSession currentSession];
NSAssert(session, #"No user session! Can't decrypt!");
NSData* key = session.encryptionKey;
NSData* decryptedData = Decrypt(value, key);
return decryptedData;
}
- (id)reverseTransformedValue:(id)value
{
UserSession* session = [UserSession currentSession];
NSAssert(session, #"No user session! Can't encrypt!");
NSData* key = session.encryptionKey;
NSData* encryptedData = Encrypt(value, key);
return encryptedData;
}
#end
The only tricky part here is that you have to be sure that the current UserSession is set up before you create the managed object context and isn't changed until after the context is saved and deallocated.
Hope this helps.
You can create custom instances of NSValueTransformer subclasses that have state (i.e. the encryption key) and pass them in to -bind:toObject:withKeyPath:options: in the options dictionary using the NSValueTransformerBindingOption key.
You won't be able to set this up in IB directly since IB references value transformers by class name, but you can do it in code. If you're feeling extra ambitious you can set up the bindings in IB and then replace them with different options in code later.
It might look something like this:
#interface EncryptingValueTransformer : NSValueTransformer
#property (nonatomic,readwrite,copy) NSData* encryptionKey;
#end
#implementation EncryptingValueTransformer
- (void)dealloc
{
_encryptionKey = nil;
}
- (id)transformedValue:(id)value
{
if (!self.encryptionKey)
return nil;
// do the transformation
return value;
}
- (id)reverseTransformedValue:(id)value
{
if (!self.encryptionKey)
return nil;
// Do the reverse transformation
return value;
}
#end
#interface MyViewController : NSViewController
#property (nonatomic, readwrite, assign) IBOutlet NSControl* controlBoundToEncryptedValue;
#end
#implementation MyViewController
// Other stuff...
- (void)loadView
{
[super loadView];
// Replace IB's value tansformer binding settings (which will be by class and not instance) with specific,
// stateful instances.
for (NSString* binding in [self.controlBoundToEncryptedValue exposedBindings])
{
NSDictionary* bindingInfo = [self.controlBoundToEncryptedValue infoForBinding: binding];
NSDictionary* options = bindingInfo[NSOptionsKey];
if ([options[NSValueTransformerNameBindingOption] isEqual: NSStringFromClass([EncryptingValueTransformer class])])
{
// Out with the old
[self.controlBoundToEncryptedValue unbind: binding];
// In with the new
NSMutableDictionary* mutableOptions = [options mutableCopy];
mutableOptions[NSValueTransformerNameBindingOption] = nil;
mutableOptions[NSValueTransformerBindingOption] = [[EncryptingValueTransformer alloc] init];
[self.controlBoundToEncryptedValue bind: binding
toObject: bindingInfo[NSObservedObjectKey]
withKeyPath: bindingInfo[NSObservedKeyPathKey]
options: mutableOptions];
}
}
}
// Assuming you're using the standard representedObject pattern, this will get set every time you want
// your view to expose new model data. This is a good place to update the encryption key in the transformers'
// state...
- (void)setRepresentedObject:(id)representedObject
{
for (NSString* binding in [self.controlBoundToEncryptedValue exposedBindings])
{
id transformer = [self.controlBoundToEncryptedValue infoForBinding: NSValueBinding][NSOptionsKey][NSValueTransformerBindingOption];
EncryptingValueTransformer* encryptingTransformer = [transformer isKindOfClass: [EncryptingValueTransformer class]] ? (EncryptingValueTransformer*)transformer : nil;
encryptingTransformer.encryptionKey = nil;
}
[super setRepresentedObject:representedObject];
// Get key from model however...
NSData* encryptionKeySpecificToThisUser = /* Whatever it is... */ nil;
for (NSString* binding in [self.controlBoundToEncryptedValue exposedBindings])
{
id transformer = [self.controlBoundToEncryptedValue infoForBinding: NSValueBinding][NSOptionsKey][NSValueTransformerBindingOption];
EncryptingValueTransformer* encryptingTransformer = [transformer isKindOfClass: [EncryptingValueTransformer class]] ? (EncryptingValueTransformer*)transformer : nil;
encryptingTransformer.encryptionKey = encryptionKeySpecificToThisUser;
}
}
// ...Other stuff
#end
OK. This was bugging me so I thought about it some more... I think the easiest way is to have some sort of "session" object and then have a "derived property" on your managed object. Assuming you have an entity called UserData with a property called encryptedData, I whipped up some code that might help illustrate:
#interface UserData : NSManagedObject
#property (nonatomic, retain) NSData * unencryptedData;
#end
#interface UserData () // Private
#property (nonatomic, retain) NSData * encryptedData;
#end
// These functions defined elsewhere
NSData* Encrypt(NSData* clearData, NSData* key);
NSData* Decrypt(NSData* cipherData, NSData* key);
#interface UserSession : NSObject
+ (UserSession*)currentSession;
- (id)initWithUserName: (NSString*)username andEncryptionKey: (NSData*)key;
#property (nonatomic, readonly) NSString* userName;
#property (nonatomic, readonly) NSData* encryptionKey;
#end
#implementation UserData
#dynamic encryptedData;
#dynamic unencryptedData;
+ (NSSet*)keyPathsForValuesAffectingUnencryptedData
{
return [NSSet setWithObject: NSStringFromSelector(#selector(encryptedData))];
}
- (NSData*)unencryptedData
{
UserSession* session = [UserSession currentSession];
if (nil == session)
return nil;
NSData* key = session.encryptionKey;
NSData* encryptedData = self.encryptedData;
NSData* decryptedData = Decrypt(encryptedData, key);
return decryptedData;
}
- (void)setUnencryptedData:(NSData *)unencryptedData
{
UserSession* session = [UserSession currentSession];
NSAssert(session, #"No user session! Can't encrypt!");
NSData* key = session.encryptionKey;
NSData* encryptedData = Encrypt(unencryptedData, key);
self.encryptedData = encryptedData;
}
#end
#implementation UserSession
static UserSession* gCurrentSession = nil;
+ (UserSession*)currentSession
{
#synchronized(self)
{
return gCurrentSession;
}
}
+ (void)setCurrentSession: (UserSession*)userSession
{
#synchronized(self)
{
gCurrentSession = userSession;
}
}
- (id)initWithUserName: (NSString*)username andEncryptionKey: (NSData*)key
{
if (self = [super init])
{
_userName = [username copy];
_encryptionKey = [key copy];
}
return self;
}
-(void)dealloc
{
_userName = nil;
_encryptionKey = nil;
}
#end
The idea here is that when a given user logs in you create a new UserSession object and call +[UserSession setCurrentSession: [[UserSession alloc] initWithUserName: #"foo" andEncryptionKey: <whatever>]]. The derived property (unencryptedData) accessor and mutator get the current session and use the key to transform the values back and forth to the "real" property. (Also, don't skip over the +keyPathsForValuesAffectingUnencryptedData method. This tells the runtime about the relationship between the two properties, and will help things work more seamlessly.)

setting / retrieving data from singleton

Apple rejected our app siting that page loads times between tabs was too long. Before I was simply calling a webview to display content managed through a CMS. Now we have implemented JSON and I am tring to preload the 5 tabs' data using the singleton design pattern. I can't seem to set the singleton value as I see in examples. On to the code:
header.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
NSString *someProperty;
...
}
#property (nonatomic, retain) NSString *someProperty;
+ (id)sharedManager;
#property (strong, nonatomic) NSString* tab3data;
#end
Implementation.m
//Create a seperate thread to download JSON thread
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
//Set JSON URL
#define GWDiOSURL [NSURL URLWithString:#"http://m.web.org/cms_mapper.php"]
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize someProperty;
- (id)init {
if (self = [super init]) {
someProperty = #"Default Property Value";
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"First", #"First");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
FirstViewController *sharedManager = [FirstViewController sharedManager];
NSLog(#"Toll%#",sharedManager);
// Do any additional setup after loading the view, typically from a nib.
//Get JSON and load into 'data'
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:GWDiOSURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
//Begin JSON Data Parsing and loading
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
//Parse JSON
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
// Load JSON into a dictionary
NSDictionary *tabData = [json objectForKey:#"mapper"];
// Get Tab3 data from dictionary
NSDictionary *tab3 = [tabData objectForKey:#"#tab3_content"];
// Load Tab3 data into a string from dictionary
NSString *html = [NSString stringWithFormat:#"%#",tab3];
// Verify content via counsel
//NSLog(#"Second Data:%#",html);
// Load content into webView
[webView loadHTMLString:html baseURL:nil];
[FirstViewController sharedManager].someProperty = #"asdf";
}
+ (id)sharedManager {
static FirstViewController *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
I need to set the value of html to the singleton. The follow line
[FirstViewController sharedManager].someProperty = #"asdf";
produces this error
Propery 'someProperty' not found on object of type 'id'.
I have been trying to get this whole process to work for days.. I appreciate the insight.
Well, your class method, sharedManager, returns an id. Try returning FirstViewController* in sharedManager.
+ (FirstViewController *)sharedManager;

Resources