Kutay Demireren
Kutay Demireren

Reputation: 650

Adding user before app actually start

I'm trying to add a user for the first time app is opened. That adding response back to me with a some sort of password, what we call Access Token. The token is using to reaching the API services.

Anyway, beside that story, what my problem is for the first time app open, I can add the user and get the token and I saved it as NSUserDefault, but I can't reach to API Services since it tries to reach services with null. After refreshing or reopening the app or switching another view and back that view will solve the issue. But just for the first time, it can't reach the service.

The problem is here, obviously, when the app opens for the first time, before the adding operation is finished, I try to reach to service what cause it to stay null. So here is the code I have:

- (void)viewDidLoad {
    [super viewDidLoad];

    //Adding user.
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // User informations.
    NSString *accessToken = [defaults objectForKey:@"accessToken"];
    if(accessToken == nil)
        [APIClient AddUser];

    //Adding the inital viewController.
    UIViewController *vc = [self viewControllerForSegmentIndex:self.typeSegmentedControl.selectedSegmentIndex];
    [self addChildViewController:vc];
    vc.view.frame = self.contentView.bounds;
    [self.contentView addSubview:vc.view];
    self.currentViewController = vc;
}

Don't hang up with what I'm doing while adding the initial viewController, rather than that please just see what happens there as I add the user and then initialize the viewController. Being asynchronous is the problem, so I'm looking a way to adding the user before the app actually started or launched.

I'm not sure in this case if I have to add the user in application:didFinishLauncingWithOptions, but I don't think so that is the problem.

Upvotes: 0

Views: 44

Answers (1)

Miknash
Miknash

Reputation: 7948

Okay, so the first thing I would do is extract token related code to the function in view controller. Let's call it tokenReceived:

-(void) tokenReceived{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // User informations.
    NSString *accessToken = [defaults objectForKey:@"accessToken"];
    if(accessToken == nil)
        [APIClient AddUser];

    //Adding the inital viewController.
    UIViewController *vc = [self viewControllerForSegmentIndex:self.typeSegmentedControl.selectedSegmentIndex];
    [self addChildViewController:vc];
    vc.view.frame = self.contentView.bounds;
    [self.contentView addSubview:vc.view];
    self.currentViewController = vc;
}

In the view did load add the following:

[[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(onGetToken) 
        name:@"getToken"
        object:nil];

then add the new method:

- (void) onGetToken
{
   [self tokenReceived]
}

and, ofcourse, when you get the token ( in app delegate or wherever you retrieve token ) send notification to observer:

// your code, saving to nsuserdefualts etc.
[[NSNotificationCenter defaultCenter] 
        postNotificationName:@"getToken" 
        object:self];

Explanation: It is a bad practice to block main thread with network - your app will not respond to any of the events and if you don't have 3g or wifi - you are stuck. User experience is bad, and that will drive users away.

On the other hand, this will open user screen, and you can put loader if you want till you notify the view controller that you actually got something. This way you will keep async nature of network and still refresh UI when you get one. If you are concerned that you will get token before opening view controller, you can add tokenReceived to view did load as well.

One more thing, you can send NSNotification with the object, and get one from NSNotification object, but in this case you just need to be notified that something happened, you don't need that data.

Upvotes: 1

Related Questions