issues make a persistent object in Objective C
-
18-09-2019 - |
Question
Attempting to make a NSObject called 'Person' that will hold the login details for my application (nothing to fancy). The app is made of a navigation controller with multiple table views but I am having issues sharing the Person object around.
Attempted to create a static object like this:
+ (Person *)sharedInstance {
static Person *sharedInstance;
@synchronized(self) {
if(!sharedInstance)
sharedInstance = [[Person alloc] init];
return sharedInstance;
}
return nil;
}
And here is the header
// Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject {
NSString *fullName;
NSString *firstName;
NSString *lastName;
NSString *mobileNumber;
NSString *userPassword;
}
@property(nonatomic, retain) NSString *fullName;
@property(nonatomic, retain) NSString *firstName;
@property(nonatomic, retain) NSString *lastName;
@property(nonatomic, retain) NSString *mobileNumber;
@property(nonatomic, retain) NSString *userPassword;
+ (Person *)sharedInstance;
-(BOOL) setName:(NSString*) fname;
-(BOOL) setMob:(NSString*) mnum;
-(BOOL) setPass:(NSString*) pwd;
@end
This object setters and getters are needed in different parts of the application. I have been attempting to access them like this
Person * ThePerson = [[Person alloc] init];
ThePerson = nil;
NSString * PersonsName;
PersonsName = [[Person sharedInstance] firstName];
Everything works well at the login screen but it dies at the next use. usually EXC_BAD_ACCESS (eek!).
Clearly I am doing something very wrong here. Is there an easier way to share objects between different a number view controllers (both coded and xib)?
Solution
Why not store this information in the NSUserDefaults
or the Keychain?
OTHER TIPS
Your +sharedInstance
method returns nil
when it should be returning the shared instance. Also, I doubt there's any value to synchronizing on that block. The method could be written more simply:
+ (Person *)sharedInstance {
static Person *sharedInstance;
if(!sharedInstance) {
sharedInstance = [[Person alloc] init];
}
return sharedInstance;
}
Note that this does not create a 'static object', since there's no such thing in Objective-C; it just assigns an object to a static variable (probably what you meant, but just wanted to make sure).
Another way to share an object among two or more view controllers within a navigation controller is to add a property to the nested view controllers, and call the setter method before navigating. For example, you could add a property such as the following:
@property (nonatomic, retain) Book *book;
to a child of the root view controller, and send it a -setBook:
message in the root view controller's -tableView:didSelectRowAtIndexPath:
method.
You're not using the shared instance pattern correctly. Your sharedInstance method should alloc and init a new Person (if it has not already been done once) and assign it to the sharedInstance static variable.
Then when you need a pointer to the person, you should use the shared instance class method, not alloc and init a new instance yourself.
Technically, if you're going for a full blown singleton, your alloc method shouldn't allow you create a new instance of a Person.
Also, I just re-read your code, and came across a bit of a WTF:
Person * ThePerson = [[Person alloc] init];
ThePerson = nil;
What is that all about? That's a memory leak, right there.
All your problems can be solved by replacing any and all lines of Person *thePerson = [[Person alloc] init];
with Person *person = [Person sharedInstance];
Your init is hinky, if you want to set the firstName of Person do it like this
Person *thePerson = [Person sharedInstance];
thePerson.name = @"John Public";
to get the name out,
NSString *personName = [[Person sharedInstance] name];
That will work in any class that #imports "Person.h"