升级到 iOS 11.3 破坏了 __weak UIAlertAction
upgrade to iOS 11.3 broke __weak UIAlertAction
昨天我将 iPhone 6s 更新为 iOS 11.3。当我打开我的应用程序时,它立即崩溃了。我追踪到以下代码的崩溃,我发现我的 'yes' UIAlertAction 为 nil。
即使在我取出 __weak 声明后,代码仍会运行并且不会崩溃,但是我的警报不会像以前那样在屏幕上弹出。我到处都使用了其中的几个警报。
我的代码有问题吗?或者这是一个合法的 11.3 iOS 错误?
更新到 11.3 后是否有其他人遇到过类似的崩溃?
此代码在 1.5 年内一直运行良好,最近没有
变化。
- (void) alertGotoAppSettings:(NSString *)title :(NSString *)msg :(UIViewController *)view
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
message:msg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction __weak *yes = [UIAlertAction
actionWithTitle:LOC(@"Yes")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// Launch Settings for GPS
if (UIApplicationOpenSettingsURLString != nil) {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (IS_IOS_10_OR_LATER) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success)
{
}];
}
else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
}];
UIAlertAction __weak *no = [UIAlertAction
actionWithTitle:LOC(@"No")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
dispatch_async(dispatch_get_main_queue(), ^{
[alert dismissViewControllerAnimated:YES completion:nil];
});
}];
[alert addAction:no];
[alert addAction:yes]; <---- 'yes' is nil here
UIAlertController __weak *weakAlert = alert;
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *strongAlert = weakAlert;
[view presentViewController:strongAlert animated:YES completion:nil];
});
}
yes
和 no
都不应该是 __weak
。同样,应该从此代码片段中删除 weakAlert
/strongAlert
模式。
仅当相关对象具有其他显式强引用时才应使用弱引用,但您只是不希望您的代码建立另一个强引用。特别是,当存在强引用循环的风险时,您可以使用 weak
。但是这里不存在这种潜在的强引用循环。坦率地说,在不涉及其他显式强引用的情况下,将 weak
与局部变量结合使用根本没有意义。
底线,weak
表示 "this object can be deallocated and this particular reference can be set to nil
when there are no strong references remaining"。但在这种情况下,由于您唯一的参考是 weak
参考,因此没有任何强参考。因此,ARC 可以自由地释放它们。
有问题的代码可能在过去有效(也许 ARC 对于何时释放对象更为保守),但在这种情况下删除这些 weak
引用是正确的。它们毫无用处,并且使对象的范围变得模糊。
昨天我将 iPhone 6s 更新为 iOS 11.3。当我打开我的应用程序时,它立即崩溃了。我追踪到以下代码的崩溃,我发现我的 'yes' UIAlertAction 为 nil。
即使在我取出 __weak 声明后,代码仍会运行并且不会崩溃,但是我的警报不会像以前那样在屏幕上弹出。我到处都使用了其中的几个警报。
我的代码有问题吗?或者这是一个合法的 11.3 iOS 错误? 更新到 11.3 后是否有其他人遇到过类似的崩溃? 此代码在 1.5 年内一直运行良好,最近没有 变化。
- (void) alertGotoAppSettings:(NSString *)title :(NSString *)msg :(UIViewController *)view
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
message:msg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction __weak *yes = [UIAlertAction
actionWithTitle:LOC(@"Yes")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// Launch Settings for GPS
if (UIApplicationOpenSettingsURLString != nil) {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (IS_IOS_10_OR_LATER) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success)
{
}];
}
else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
}];
UIAlertAction __weak *no = [UIAlertAction
actionWithTitle:LOC(@"No")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
dispatch_async(dispatch_get_main_queue(), ^{
[alert dismissViewControllerAnimated:YES completion:nil];
});
}];
[alert addAction:no];
[alert addAction:yes]; <---- 'yes' is nil here
UIAlertController __weak *weakAlert = alert;
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *strongAlert = weakAlert;
[view presentViewController:strongAlert animated:YES completion:nil];
});
}
yes
和 no
都不应该是 __weak
。同样,应该从此代码片段中删除 weakAlert
/strongAlert
模式。
仅当相关对象具有其他显式强引用时才应使用弱引用,但您只是不希望您的代码建立另一个强引用。特别是,当存在强引用循环的风险时,您可以使用 weak
。但是这里不存在这种潜在的强引用循环。坦率地说,在不涉及其他显式强引用的情况下,将 weak
与局部变量结合使用根本没有意义。
底线,weak
表示 "this object can be deallocated and this particular reference can be set to nil
when there are no strong references remaining"。但在这种情况下,由于您唯一的参考是 weak
参考,因此没有任何强参考。因此,ARC 可以自由地释放它们。
有问题的代码可能在过去有效(也许 ARC 对于何时释放对象更为保守),但在这种情况下删除这些 weak
引用是正确的。它们毫无用处,并且使对象的范围变得模糊。