gpt4 book ai didi

ios - UISplitViewController 在 iOS 9 中是否存在保留周期错误?

转载 作者:可可西里 更新时间:2023-11-01 03:32:10 24 4
gpt4 key购买 nike

在下面的例子中,我展示了一个 UIViewController,它有一个 UIStackViewController 作为它的 child :

UIViewController *splitViewParentVC = UIViewController.new;

UIViewController *masterVC = UIViewController.new;
UIViewController *detailVC = UIViewController.new;

UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = @[masterVC, detailVC];

[splitViewParentVC addChildViewController:splitViewController];
[splitViewParentVC.view addSubview:splitViewController.view];
[splitViewController didMoveToParentViewController:splitViewParentVC];
splitViewController.view.frame = splitViewParentVC.view.bounds;
splitViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

__weak UISplitViewController *wSplitViewController = splitViewController;

[self presentViewController:splitViewParentVC animated:YES completion:nil];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (wSplitViewController) {
NSLog(@"the split view controller has leaked");
} else {
NSLog(@"the split view controller didn't leak");
}
});
}];
});

在 iOS 9 和 9.1 中,上面的代码将打印 the split view controller has leaked,表明 UIStackViewController 已经泄漏(更重要的是,它也泄漏了它的主视图 Controller 和详细 View Controller )。

最佳答案

是的,一个保留周期错误是confirmed由 Apple Staff 存在于 iOS 9 中。

我测试过,在 iOS 8.4 中不存在 retain cycle,但在 iOS 9.0 和 9.1 中存在。 漏洞似乎从 iOS 9.2 开始修复(在 iOS 9.2 模拟器上的 Xcode 7.2 beta 2 中测试)我整理了一个 sample project轻松确认 UISplitViewController 是否导致自身泄漏(只需运行它并检查控制台输出)。

这也测试了允许释放主视图 Controller 和细节 View Controller 的尝试。可以看出,主视图 Controller 似乎仍由 UISplitViewController 保留,即使它已从 UISplitViewController.viewControllers 数组属性中删除。

下面是示例项目的代码:

- (void)viewDidLoad {
[super viewDidLoad];

[self testSplitViewControllerRetainCycleWithCompletion:^{
[self testManuallyFreeingUpMasterAndDetailViewControllers];
}];
}

- (void)testSplitViewControllerRetainCycleWithCompletion:(void (^)())completion {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

UIViewController *splitViewParentVC = UIViewController.new;

UIViewController *masterVC = UIViewController.new;
UIViewController *detailVC = UIViewController.new;

UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = @[masterVC, detailVC];
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
splitViewController.preferredPrimaryColumnWidthFraction = 0.3125; // 320 / 1024
splitViewController.minimumPrimaryColumnWidth = 100;

[splitViewParentVC addChildViewController:splitViewController];
[splitViewParentVC.view addSubview:splitViewController.view];
[splitViewController didMoveToParentViewController:splitViewParentVC];
splitViewController.view.frame = splitViewParentVC.view.bounds;
splitViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

__weak UISplitViewController *wSplitViewController = splitViewController;
__weak UIViewController *wMaster = masterVC;
__weak UIViewController *wDetail = detailVC;

[self presentViewController:splitViewParentVC animated:YES completion:nil];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (wSplitViewController) {
NSLog(@"the split view controller has leaked");
} else {
NSLog(@"the split view controller didn't leak");
}
if (wMaster) {
NSLog(@"the master view controller has leaked");
} else {
NSLog(@"the master view controller didn't leak");
}
if (wDetail) {
NSLog(@"the detail view controller has leaked");
} else {
NSLog(@"the detail view controller didn't leak");
}

completion();
});
}];
});
});
}

- (void)testManuallyFreeingUpMasterAndDetailViewControllers {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

UIViewController *splitViewParentVC = UIViewController.new;

UIViewController *masterVC = UIViewController.new;
UIViewController *detailVC = UIViewController.new;

UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = @[masterVC, detailVC];
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
splitViewController.preferredPrimaryColumnWidthFraction = 0.3125; // 320 / 1024
splitViewController.minimumPrimaryColumnWidth = 100;

[splitViewParentVC addChildViewController:splitViewController];
[splitViewParentVC.view addSubview:splitViewController.view];
[splitViewController didMoveToParentViewController:splitViewParentVC];
splitViewController.view.frame = splitViewParentVC.view.bounds;
splitViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

__weak UIViewController *wMaster = masterVC;
__weak UIViewController *wDetail = detailVC;

[self presentViewController:splitViewParentVC animated:YES completion:nil];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];

splitViewController.viewControllers = @[UIViewController.new, UIViewController.new];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (wMaster) {
NSLog(@"the master view controller has STILL leaked even after an attempt to free it");
} else {
NSLog(@"the master view controller didn't leak");
}
if (wDetail) {
NSLog(@"the detail view controller has STILL leaked even after an attempt to free it");
} else {
NSLog(@"the detail view controller didn't leak");
}
});
});
});
}

更新:漏洞似乎已从 iOS 9.2 开始修复(已在 iOS 9.2 模拟器上的 Xcode 7.2 beta 2 中测试)

关于ios - UISplitViewController 在 iOS 9 中是否存在保留周期错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33271149/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com