2017-09-13 10 views
0

は私がネイティブに反応のためのネイティブmoduleを持って、それはSafariのビュー・コントローラ開きます「コレクションは列挙されているうちに突然変異されました」というエラーと戦う方法は?

RCTSFSafariViewController.m:

#import "RCTSFSafariViewController.h" 

@implementation RCTSFSafariViewController 

@synthesize bridge = _bridge; 

RCT_EXPORT_MODULE(); 

- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller { 
    [self.bridge.eventDispatcher sendAppEventWithName:@"SFSafariViewControllerDismissed" body:nil]; 
} 

RCT_EXPORT_METHOD(openURL:(NSString *)urlString params:(NSDictionary *)params) { 
    NSURL *url = [[NSURL alloc] initWithString:urlString]; 

    SFSafariViewController *safariViewController = [[SFSafariViewController alloc] initWithURL:url]; 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:safariViewController]; 

    [navigationController setNavigationBarHidden:YES animated:NO]; 
    safariViewController.delegate = self; 

    if ([params objectForKey:@"tintColor"]) { 
    UIColor *tintColor = [RCTConvert UIColor:params[@"tintColor"]]; 

    if([safariViewController respondsToSelector:@selector(setPreferredControlTintColor:)]) { 
     safariViewController.preferredControlTintColor = tintColor; 
    } else { 
     safariViewController.view.tintColor = tintColor; 
    } 
    } 

    dispatch_sync(dispatch_get_main_queue(), ^{ 
    [rootViewController.rootViewController.presentedViewController presentViewController:navigationController animated:YES completion:^{ 
     [self.bridge.eventDispatcher sendDeviceEventWithName:@"SFSafariViewControllerDidLoad" body:nil]; 
    }]; 
    }); 
} 

RCT_EXPORT_METHOD(close) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    UIViewController *rootViewController = [[[UIApplication sharedApplication] delegate] window].rootViewController; 
    [rootViewController dismissViewControllerAnimated:YES completion:nil]; 
    }); 
} 

@end 

RCTSFSafariViewController.h:それはシミュレータと私のiPhoneに適しています

#import <React/RCTBridgeModule.h> 
#import <React/RCTConvert.h> 
#import <React/RCTEventDispatcher.h> 
#import <UIKit/UIKit.h> 

@import SafariServices; 

@interface RCTSFSafariViewController : NSObject <RCTBridgeModule, SFSafariViewControllerDelegate> 
@end 

しかし、多くのユーザーがこのようなクラッシュに直面しています(クラッシュスティクスによれば):

Collection <__NSArrayM: 0x14e3bd20> was mutated while being enumerated.' was thrown while invoking openURL on target SFSafariViewController with params ("https://example.com", { }) 

このコードには配列や列挙型の構造が存在しないという問題があります。 dispatch_asyncによって引き起こされる可能性があるという考えがあります。なぜなら、削除するとアプリケーションがクラッシュするのを止めるからですが、SVCを呼び出した後はゆっくりと動作します。

私は間違っていますか?

答えて

0

これは非メインキューで呼び出されていると仮定します。メインキューにある場合は、dispatch_syncがデッドロックする必要があります。メインキューからほとんどのUIKitオブジェクトと対話することは安全ではありません。これにはSFSafariViewControllerが含まれている可能性があります(明示的な文書がないと安全でない場合は、そうではありません)。

dispatch_syncを呼び出すのは一般的に危険です(デッドロックにつながることはありません)。この場合は不要です。あなたは間違いなくここでdispatch_asyncを使用することができます。

このメソッド全体を、メインキューを呼び出すdispatch_asyncに移動する必要があります。

+0

私はdispatch_asyncを使い、dispatch_syncは私の絶望的な実験でした。しかし、最後の段落は可能な解決策であるようです。私はそれを試してみます。とにかく、答えに大きな感謝。 – devtwo

+0

どういうわけか、メソッド全体を 'dispatch_async'にラップすると、SFSafariViewControllerを呼び出すときにデッドロックが発生します:( – devtwo

+0

メソッド全体をラップして' dispatch_sync'を削除するか、 'dispatch_sync'を残していますか?' dispatch_sync'コールを削除しないと、 –

関連する問題