【问题标题】:Why does my app crash on iOS 10 when repeatedly presenting and using UIImagePickerControllers?为什么我的应用在 iOS 10 上反复呈现和使用 UIImagePickerControllers 时会崩溃?
【发布时间】:2017-03-23 14:50:01
【问题描述】:

我们几年前开发的一款应用在 iOS 10 推出后就开始崩溃。该应用程序反复呈现 UIImagePickerControllers 以允许用户捕获主题的几张照片。这样做 40 多次后,应用程序崩溃了。这可以在我们测试过的所有设备上重现,但在引入 iOS 10 之前不会发生。我们在 Info.plist 文件中有 NSCameraUsageDescription 和 NSPhotoLibraryUsageDescription 键。

我创建了一个演示问题的最小示例应用程序。以下是最终导致崩溃的代码:

- (IBAction) cameraPressed:(id) sender {
    self.picker = [[UIImagePickerController alloc] init];
    self.picker.sourceType =  UIImagePickerControllerSourceTypeCamera;
    self.picker.delegate = self;
    self.picker.allowsEditing = NO;
    [self presentViewController:self.picker animated:YES completion:nil];
}

当用户反复使用连接到此 IBAction 的相机按钮时,它最终会开始变慢(选择器的呈现开始花费更长的时间),并最终崩溃(通常在相机使用 50 次以上之后)。不会产生崩溃日志,尽管当连接到 Xcode 时,控制台中会出现这样的输出,导致崩溃:

2016-11-04 20:30:11.884984 WLPBeta[2747:275474] [MC] Invalidating cache
2016-11-04 20:30:11.890776 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:30:13.017608 WLPBeta[2747:275091] [MC] Invalidating cache
2016-11-04 20:30:13.018312 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:30:19.271720 WLPBeta[2747:276311] [MC] Invalidating cache
2016-11-04 20:30:19.279462 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:08.229294 WLPBeta[2747:278515] [MC] Invalidating cache
2016-11-04 20:32:08.273941 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:09.335711 WLPBeta[2747:278514] [MC] Invalidating cache
2016-11-04 20:32:09.342161 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:14.193376 WLPBeta[2747:278515] [MC] Invalidating cache
2016-11-04 20:32:14.213902 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:47.944657 WLPBeta[2747:275091] [MC] Invalidating cache
2016-11-04 20:32:47.972053 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:48.550934 WLPBeta[2747:279485] [MC] Invalidating cache
2016-11-04 20:32:48.575065 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:50.855308 WLPBeta[2747:279485] [MC] Invalidating cache
2016-11-04 20:32:50.856329 WLPBeta[2747:273019] [MC] Reading from public effective user settings.
2016-11-04 20:32:52.201535 WLPBeta[2747:275091] [GatekeeperXPC] Connection to assetsd was interrupted or assetsd died

我还向 Apple 发布了错误报告,并将其添加到开放雷达:http://www.openradar.me/radar?id=4941109843197952

有人遇到过这个问题吗?是否有一个修复程序可以让我们在不使用 Xcode 8 重新编译应用程序的情况下克服这个问题?不幸的是,我们使用的第三方库尚未为 Xcode 8 和 iOS 10 SDK 做好准备,因此我们仍在使用 Xcode 7.3.1 构建应用程序。

编辑:这是一个 Github 存储库的链接,其中包含可用于演示问题的示例应用程序。

https://github.com/lolay/ImagePickerTest

编辑 2:如果我更改代码以便在 viewDidLoad 中分配和初始化选取器,在使用相机按钮的次数大致相同后,它仍然会崩溃。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.picker = [[UIImagePickerController alloc] init];
    self.picker.sourceType =  UIImagePickerControllerSourceTypeCamera;
    self.picker.allowsEditing = NO;
}

- (IBAction) cameraPressed:(id) sender {
    [self presentViewController:self.picker animated:YES completion:nil];
}

【问题讨论】:

  • 你用过仪器吗?也许你有内存泄漏或引用循环。
  • 我们有并且没有检测到任何泄漏或参考周期。如问题中所述,我将问题归结为一个最小的示例应用程序,只需将几行代码添加到 Xcode 创建的骨架项目中。我添加的代码显示在问题中。
  • 每次按下按钮时您都必须初始化 imagePicker 有什么特别的原因吗?为什么不将所有代码行移至 viewDidLoad 并在按下按钮时触发 presentViewController 方法?
  • 没有特别的原因,但是如果我将选取器的初始化移到 viewDidLoad 中,在拍摄大约相同数量的照片后,我仍然会遇到崩溃。
  • 您可能遇到了引用计数循环,请将 self.picker.delegate 对象设置为其他对象(不是视图控制器中的 self)以避免引用计数循环问题。

标签: ios objective-c iphone uiimagepickercontroller


【解决方案1】:

您的 UIImagePickerController 被定义为 STRONG。

请把它改成weak或者在视图被销毁之前确保对象为nil。

【讨论】:

    【解决方案2】:

    试试这个代码。

    - (IBAction) cameraPressed:(id) sender {
       if (self.picker == nil){
          self.picker = [[UIImagePickerController alloc] init];
       }
    
        self.picker.sourceType =  UIImagePickerControllerSourceTypeCamera;
        self.picker.delegate = self;
        self.picker.allowsEditing = NO;
        [self presentViewController:self.picker animated:YES completion:nil];
    }
    

    【讨论】:

      【解决方案3】:

      您是否尝试过在 cameraPressed() 函数中声明 Imagepicker 变量

      - (IBAction) cameraPressed:(id) sender {
         UIImagePickerController *picker = [[UIImagePickerController alloc] init];
          picker.sourceType =  UIImagePickerControllerSourceTypeCamera;
          picker.delegate = self;
          picker.allowsEditing = NO;
          [self presentViewController:self.picker animated:YES completion:nil];
      }
      

      【讨论】:

        【解决方案4】:

        您需要明确解除 UIImagePickerController,即使它似乎是自动执行的。如果不这样做,它可能会保留视图控制器,从而导致内存问题。

        来自UIImagePickerControllerDelegate documentation

        如果您将图像选择器的 showsCameraControls 属性设置为 NO 并且 提供自己的自定义控件,可以拍多张照片 在关闭图像选择器界面之前。但是,如果你设置 属性为 YES,您的委托必须关闭图像选择器界面 用户拍照或取消操作后。

        默认情况下,该属性为 YES,因此您需要关闭。

        使用类似于以下的内容:

        - (IBAction) cameraPressed:(id) sender {
            UIImagePickerController* picker = [[UIImagePickerController alloc] init];
            picker.sourceType =  UIImagePickerControllerSourceTypeCamera;
            picker.allowsEditing = NO;
            picker.delegate = self;
            [self presentViewController:picker animated:YES completion:nil];
        }
        
        - (void) imagePickerController:(UIImagePickerController *)picker
            didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
        {
            [self dismissViewControllerAnimated:YES completion:nil];
        }
        
        - (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker
        {
            [self dismissViewControllerAnimated:YES completion:nil];
        }
        

        【讨论】:

          猜你喜欢
          • 2020-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多