performFetchWithCompletionHandlerを使用してRSSフィードのバックグラウンドフェッチを実装しようとしていますが、完了ハンドラーを呼び出したい場合はnilです。
self.completionHandlerへの参照を保持する方法がありませんか?
self.completionHandlerを正しく宣言していますか?
アプリデリゲート内:
//background fetch new RSS Feeds
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
MasterViewController *navigationController = [mainStoryboard instantiateViewControllerWithIdentifier:@"MasterView"];
MasterViewController *viewController = navigationController;
[viewController startParsingWithCompletionHandler2: ^ (UIBackgroundFetchResult completionHandler2){
completionHandler (UIBackgroundFetchResultNewData);
}];
}
メインビューコントローラの場合:
@property (nonatomic, strong) void (^completionHandler)(UIBackgroundFetchResult);
- (void) startParsingWithCompletionHandler2:(void (^)(UIBackgroundFetchResult))completionHandler2
{
self.completionHandler = completionHandler2;
if (self.completionHandler) {
NSLog(@"completionHandler");
}else{
NSLog(@"not completionHandler");
}
[self performSelector: @selector(stopParsing) withObject: nil afterDelay: PARSER_TIME_LIMIT];
[self.activityIndicator startAnimating];
numberOfCompletedStories = 0;
[self.parserArray removeAllObjects];
//check for RSS Site data updates
for (int lCounter = 0; lCounter < self.rssFeedAddresses.count; lCounter ++) {
RSSParser *parser = [[RSSParser alloc] init];
[parser setDelegate: self];
[self.parserArray addObject: parser];
[parser setSiteTitle: [self.rssFeedNames objectAtIndex: lCounter]];
[NSThread detachNewThreadSelector: @selector(begin:) toTarget: parser withObject: [self.rssFeedAddresses objectAtIndex: lCounter]];
}
if (self.completionHandler) {
NSLog(@"#2 completionHandler");
}else{
NSLog(@"#2 not completionHandler");
}
}
- (void) storyIsDone//called when parser completed one rss feed
{
numberOfCompletedStories ++;
if (self.completionHandler) {
NSLog(@"storyIsDone YES completion handler %i", numberOfCompletedStories);
}else{
NSLog(@"storyIsDone Not completion handler");
}
if (numberOfCompletedStories == self.rssFeedAddresses.count)
{
//if all the feeds are done cancel time-out timer
[NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(stopParsing) object: nil];
[self.activityIndicator stopAnimating];
[self.refreshControl endRefreshing];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reloadRSSfeeds) name: @"ReloadFeeds" object: nil];
canRefresh = YES;
NSLog(@"call back");
[self performSelectorOnMainThread: @selector(callCompletion) withObject: self waitUntilDone: YES];
}//else not yet complete
}
- (void) callCompletion
{
if (self.completionHandler) {
NSLog(@"callCompletion YES completion handler");
self.completionHandler (UIBackgroundFetchResultNewData);
}else{
NSLog(@"callCompletion Not completion handler");
}
}
出力は次のとおりです。
completionHandler
#2 completionHandler
storyIsDone Not completion handler
storyIsDone Not completion handler
storyIsDone Not completion handler
storyIsDone Not completion handler
storyIsDone Not completion handler
storyIsDone Not completion handler
storyIsDone Not completion handler
call back
callCompletion Not completion handler
クラスが正しく初期化されていません
バックグラウンドフェッチにperformFetchWithCompletionHandlerを使用する場合-メソッドが異なる順序で呼び出されるため、一部のオブジェクトが適切に初期化されません。
アプリがフォアグラウンドで起動されると、これらのメソッドが呼び出されます:(順番に)
initWithCoder awakeFromNib viewDidLoad dispatchLoadingOperation viewDidAppear
バックグラウンドフェッチを実行する場合、メソッドは次の順序で呼び出されます。
initWithCoder awakeFromNib startParsingWithCompletionHandler2 viewDidLoad dispatchLoadingOperation viewDidAppear
特に注意:vieDidLoadは、フォアグラウンドで実行されているときに解析を開始するdispatchLoadingOperationの前に呼び出されました。
バックグラウンドで実行している場合、viewDidLoadの前にstartParsingWithCompletionHandler2(バックグラウンドで実行しているときにも解析を開始します)が呼び出されました。
いくつかのオブジェクトがviewDidLoadで初期化されたため、解析が予想よりも早く開始され、解析結果を格納するために配列が初期化されませんでした。これは、アプリが起動していないように見えました。
完了ハンドラーのコールバックがnilであることを確認しているときに、実際の問題はクラスが正しくセットアップされていないことでした。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加