IOS11 SDK cannot access app delegate

- (NSString *)getAuthorizationHeader{
    iKMAppDelegate *delegate = (iKMAppDelegate *)[UIApplication sharedApplication].delegate;
    NSString *header = [NSString stringWithFormat:@"Bearer %@", delegate.appDataObject.oauth2AcessToken];
    return header;
}

      

this method will get a warning in XCode9

[UIApplication delegate] must be called from main thread only

      

and I don't think submitting to the main queue will work for my function. so how to correct this warning correctly?

+3


source to share


2 answers


There is no access to the UIApplication delegate on the main thread, but you can easily do this using dispatch_sync

- (NSString *)getAuthorizationHeader{
    __block iKMAppDelegate *delegate;
    if([NSThread isMainThread]) {
        delegate = (iKMAppDelegate *)[UIApplication sharedApplication].delegate;
    } else {
        dispatch_sync(dispatch_get_main_queue(), ^{
            delegate = (iKMAppDelegate *)[UIApplication sharedApplication].delegate;
        });
    }
    NSString *header = [NSString stringWithFormat:@"Bearer %@", delegate.appDataObject.oauth2AcessToken];
    return header;
}

      



In contrast dispatch_async

, the function dispatch_sync

will wait for the block to complete before returning.

C dispatch_sync

needs to check if the function is executing from the main thread, which can cause a deadlock.

+4


source


You can make a pointer to the AppDelegate before the background function is called. And get it from this pointer.

<...Main thread in app...>
[[MyDelegateHolder holder] setDelegate: (iKMAppDelegate *)[UIApplication sharedApplication].delegate];

<...RunBackground task...>
[[MyDelegateHolder holder].delegate methodCall];

<...In MyDelegateHolder delegate method  ....>
- (iKMAppDelegate*)delegate
{
  if (self.delegate == nil)
  {
    <Assert or...>
    runSyncOnMainThread(^(){//you should get delegate in sync method from the main thread
       self.delegate = (iKMAppDelegate *)[UIApplication sharedApplication].delegate;
     });
  }

  return self.delegate;
}

      



In my example MyDelegateHolder

, a singleton.
If you need multithreaded access before the delegate is set, don't forget about access locks (or mark the field as atomic).

0


source







All Articles