0

I don't know if I'm doing this properly. I'm working on a large application in which a user must log in and and interact with a variety of functionality and data. There are many view controllers that need to have access to this user object.

The following snippet is the moment when the user logs in and now I have a user object to use across my app. Just in this case I'm using dummy data.

User *user = [User new];
[user setupTempOfflineData];

self.newViewController.user = user;

[self containerAddChildViewController:self.newViewController];

In the newViewController is the property:

@property (nonatomic, strong) User *user;

Now NewViewController may have many children and those children have view controllers of their own. All of them given a strong reference to the user. Additional information such as a list of registered groups or content that the user had created remains as well. And sometimes I'll either access downloaded information via the user object, or just store and share references to the arrays/data themselves.

Something in my head is telling me I should be using a singleton or some other design pattern I'm just not familiar with. Thus bringing me here to ask the question:

Am I doing this right?

Edit: Informative link on KVO

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    That's one way to do it. There are dozens, and no one "optimal" way. (Using a singleton/static, BTW, is sometimes necessary, but should not be your first thought.) – Hot Licks Feb 08 '14 at 20:03

3 Answers3

2

You can use singleton pattern on User class. e.g.

User.h file

@interface User : NSObject

+ (User*)currentUser;

//...
// Some properties
//...

//...
// Some methods
//...

@end

User.m file

//...
+ (User*)currentUser
{
    static User *user = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        user = [[self alloc] init];
    });

    return user;
}
//...

Import "User.h" file in your .pch file.

Now you can access to your user object by calling
[User currentUser];

arturdev
  • 10,884
  • 2
  • 39
  • 67
  • Lets say you have a screen that shows a list of groups that the User is in. Would you access the user information via the currentUser object and use it in all the necessary UITableView delegate and datasource methods. Or would you keep a weak reference or copy of just the array in question like: self.groupArray = [User currentUser].groupArray? – Joshua Lieberman Feb 09 '14 at 18:08
  • I just call [User currentUser].neededProperty when I need it :) – arturdev Feb 09 '14 at 20:17
1

I'm using the Singleton pattern in my applications, and use lazy instantiation to load that user.

So in your newViewController.m

/**
  * lazy instantiation of User
 */
- (User *) user {
    if (!_user){
        _user = [User getUser];
    }
    return _user;
}

in User.h

@interface User : NSObject

/**
 * Singleton
 */
+ (User *) getUser;

@end

And finally in your User.m

#import "User.h"

/*
 * Singleton
 */
static User *singletonUser = nil;

@implementation User

/**
 * Designated initializer
 */
- (id) init {
    self = [super init];
    if (self != nil) {
        // Load your user from storage / CoreData / etc.
        [self setupTempOfflineData];
    }
    return self;
}

/**
 * Singleton
 */
+ (User *) getUser {
    if (singletonUser == nil) {
        singletonUser = [[self alloc] init];
    }
    return singletonUser;
}
@end

So now you can use self.user in your NewViewController.

Rool Paap
  • 1,918
  • 4
  • 32
  • 39
0

What you're doing should work. Also have you thought about protocol and delegate? You may want to consider this design pattern in the event that you want the NewViewController (or other view controllers) to be notified when the User object has changed (KVO/Notificaiton are another design patterns).

User.h

@class User;
@protocol userProtocol <NSObject>
-(void) userObjectDidGetUpdated:(User*) u;
@end
@interface User:NSObject {}
@property (nonatomic,weak) id <userProtocol> delegate; // use weak here to prevent reference cycle
@end

User.m -- call notifyDelegatesUserObjectHasChanged when you want to notify the delegates to get the updated User object

@implementation
@synthesize delegate;
-(void) notifyDelegatesUserObjectHasChanged {
    [[self delegate] userObjectDidGetUpdated:self];
}
@end

Now, you can register the view controller to get the updated User object as follow...

NewViewController.h

#import "User.h"
@interface NewViewController:UIViewController <userProtocol> {}

NewViewController.m

@implementation
-(void) userObjectDidGetUpdated:(User*) u {
    // this callback method will get called when the User object changes
}
@end
MobileDev
  • 3,750
  • 4
  • 32
  • 35
  • So using this, the user is limited to a single delegate. I'd have to use an array of objects that conform to the userProtocol delegate. But at that point this starts sounding a lot like what KVO/Notification is all about. – Joshua Lieberman Feb 09 '14 at 16:21