- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的 View Controller (下面的代码)是从 Storyboard转场(附加到 UIButton)中模态呈现的。一旦点击其中一个(动态生成的)按钮,它就会被关闭。由于某种原因,它随后没有被释放(保留计数为 1)。
显然,首先要考虑的是两个对象(PPAPI 和 PPObjectCache),它们将此对象保存为委托(delegate)(在 viewDidLoad 中注册),但是它们都使用弱引用,如果我能得到任何其他内容,它们将自动被 ARC 清空保留它以释放它。我已验证这些对象没有持有对此 View Controller 的强引用。
我已经使用 Instruments(Allocations 配置文件)检查了这个对象的保留/释放,报告显示在代码下方。如您所见,不平衡存在于 UIKit 或 Foundation 代码中,但我很难看出确切位置或原因。
谁能找出 UIKit 或 Foundation 保留我的 View Controller 的原因?
#import "PPLoginViewController.h"
#import "PPAppDelegate.h"
@interface PPLoginViewController () {
NSArray *employeeIDs;
}
@end
@implementation PPLoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
PPAPI *api = [PPAPI api];
[api subscribeToViewsOfType:@"employees" delegate:self];
[[PPObjectCache cache] subscribeToChangesToObjectsOfType:@"worker" delegate:self];
[api callMethod:@"main.tasks.get_employees" withParameters:@{} callback:nil];
}
// PPAPI view subscription delegate method
- (void)receivedObjectIDs:(NSArray *)objectIDs forViewType:(NSString *)viewType {
NSLog(@"%@: GOT VIEW", self);
dispatch_async(dispatch_get_main_queue(), ^{
employeeIDs = objectIDs;
[self reload];
});
}
// PPObjectCache delegate method
- (void)objectChanged:(id)object {
dispatch_async(dispatch_get_main_queue(), ^{
[self reload];
});
}
- (void)reload {
[[self.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject isKindOfClass:[UIButton class]];
}]] makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIDevice *currentDevice = [UIDevice currentDevice];
CGFloat y = 75.f;
for (NSNumber *employeeID in employeeIDs) {
NSDictionary *employee = [[PPObjectCache cache] objectOfType:@"worker" withID:employeeID];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:employee[@"name"] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont boldSystemFontOfSize:18.f];
button.tag = [employeeID integerValue];
button.frame = CGRectMake((self.view.bounds.size.width - 240.f) / 2.f, y, 240.f, currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad ? 60.f : 45.f);
[button addTarget:self action:@selector(login:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
y += currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad ? 75.f : 65.f;
}
}
// UIButton action from above
- (void)login:(UIButton *)sender {
PPAppDelegate *delegate = (PPAppDelegate *)[UIApplication sharedApplication].delegate;
delegate.loggedInEmployee = [[PPObjectCache cache] objectOfType:@"worker" withID:@(sender.tag)];
// self.logoutButton is an @property (weak) set from the presenting view controller
self.logoutButton.title = [NSString stringWithFormat:@"Logout %@", delegate.loggedInEmployee[@"initials"]];
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
分配报告如下(抱歉格式不佳)。如您所见,我的应用程序代码负责的事件都是平衡的(显示为保留/释放组或紧随其后的是平衡调用)。 UIKit 或 Foundation 中的某些东西没有释放我的 View Controller !
# Event Type ∆ RefCt RefCt Timestamp Responsible Library Responsible Caller
0 Malloc +1 1 00:19.062.502 UIKit -[UIClassSwapper initWithCoder:]
1 Retain +1 2 00:19.062.991 UIKit -[UIRuntimeConnection initWithCoder:]
2 Retain +1 3 00:19.063.036 UIKit -[UIRuntimeConnection initWithCoder:]
3 Retain +1 4 00:19.063.230 UIKit UINibDecoderDecodeObjectForValue
4 Retain +1 5 00:19.063.274 UIKit UINibDecoderDecodeObjectForValue
5 Retain +1 6 00:19.063.315 Foundation -[NSObject(NSKeyValueCoding) setValue:forKey:]
6 Retain +1 7 00:19.063.388 UIKit -[UINib instantiateWithOwner:options:]
Release (2) -2 00:19.063.568 UIKit -[UINibDecoder finishDecoding]
8 Release -1 5 00:19.063.599 UIKit -[UINibDecoder finishDecoding]
10 Release -1 3 00:19.063.722 UIKit -[UIRuntimeConnection dealloc]
11 Release -1 2 00:19.063.755 UIKit -[UIRuntimeConnection dealloc]
12 Retain +1 3 00:19.063.920 UIKit -[UIStoryboardSegue initWithIdentifier:source:destination:]
Retain/Release (2) 00:19.067.387 Purchase -[PPMasterViewController prepareForSegue:sender:]
15 Retain +1 4 00:19.072.460 UIKit -[UIViewController setChildModalViewController:]
16 Retain +1 5 00:19.076.305 UIKit -[UINib instantiateWithOwner:options:]
17 Retain +1 6 00:19.076.366 UIKit -[UINib instantiateWithOwner:options:]
18 Retain +1 7 00:19.076.582 UIKit -[UIProxyObject initWithCoder:]
19 Retain +1 8 00:19.076.587 UIKit -[UIRuntimeConnection initWithCoder:]
20 Retain +1 9 00:19.080.167 UIKit UINibDecoderDecodeObjectForValue
21 Retain +1 10 00:19.080.230 UIKit UINibDecoderDecodeObjectForValue
22 Release -1 9 00:19.080.449 UIKit -[UINib instantiateWithOwner:options:]
23 Release -1 8 00:19.080.507 UIKit -[UINib instantiateWithOwner:options:]
24 Release -1 7 00:19.080.578 UIKit -[UINibDecoder finishDecoding]
Release (2) -2 00:19.080.602 UIKit -[UINibDecoder finishDecoding]
26 Release -1 5 00:19.080.716 UIKit -[UIRuntimeConnection dealloc]
Retain/Release (2) 00:19.081.788 Purchase -[PPAPI subscribeToViewsOfType:delegate:]
Retain/Release (2) 00:19.081.866 Purchase -[PPObjectCache subscribeToChangesToObjectsOfType:delegate:]
32 Retain +1 5 00:19.089.975 UIKit -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:]
33 Retain +1 6 00:19.091.352 UIKit __91-[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:]_block_invoke_0238
Retain/Release (2) 00:19.105.379 UIKit -[UIResponder becomeFirstResponder]
36 Retain +1 7 00:19.106.122 UIKit -[UIViewController presentViewController:withTransition:completion:]
37 Retain +1 8 00:19.106.142 UIKit -[UIViewController presentViewController:withTransition:completion:]
38 Release -1 7 00:19.108.717 UIKit _UIApplicationHandleEvent
39 Release -1 6 00:19.109.517 UIKit -[UIStoryboardSegue dealloc]
40 Release -1 5 00:19.109.534 UIKit _UIApplicationHandleEvent
41 Release -1 4 00:19.109.581 UIKit -[UIStoryboardScene dealloc]
Retain/Autorelease/Release (5) +1 00:19.145.293 Foundation -[NSConcreteHashTable countByEnumeratingWithState:objects:count:]
Retain (2) +2 00:19.151.847 Purchase -[PPLoginViewController receivedObjectIDs:forViewType:]
Retain (2) +2 00:19.151.874 Purchase __copy_helper_block_
Release (2) -2 00:19.151.888 Purchase -[PPLoginViewController receivedObjectIDs:forViewType:]
Release (2) -2 00:19.278.813 Purchase __destroy_helper_block_
48 Release -1 4 00:19.541.189 UIKit -[UIWindowController transitionViewDidComplete:fromView:toView:removeFromView:]
Retain/Release (2) 00:19.996.260 UIKit -[UIViewController _dismissViewControllerWithTransition:from:completion:]
51 Release -1 3 00:19.996.269 UIKit -[UIViewController _dismissViewControllerWithTransition:from:completion:]
52 Release -1 2 00:19.996.302 UIKit -[UIPeripheralHost(UIKitInternal) _stopPinningInputViewsOnBehalfOfResponder:]
53 Retain +1 3 00:19.996.776 UIKit -[UIViewController _dismissViewControllerWithTransition:from:completion:]
54 Retain +1 4 00:20.001.379 UIKit __91-[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:]_block_invoke_0238
55 Release -1 3 00:20.002.196 UIKit -[UIViewController _dismissViewControllerWithTransition:from:completion:]
56 Retain +1 4 00:20.432.653 UIKit -[UIViewController _didFinishDismissTransition]
57 Release -1 3 00:20.432.658 UIKit -[UIViewController setChildModalViewController:]
58 Release -1 2 00:20.432.662 UIKit -[UIViewController _didFinishDismissTransition]
59 Release -1 1 00:20.432.706 UIKit -[UIWindowController transitionViewDidComplete:fromView:toView:removeFromView:]
Retain/Autorelease (2) +1 00:20.663.794 Foundation hashProbe
最佳答案
正如我所料,这是我自己的愚蠢错误,但我会在这里回答它以防它对任何人有用!
PPAPI
维护一个NSHashTable
,其中包含 View 订阅的弱引用,如果订阅的对象被释放,ARC 将自动将其清零。看起来,当从 NSHashTable
获取对象时,它们会被保留,然后由 Foundation 自动释放。
PPAPI 在后台 GCD 队列上的 while(1)
循环中访问 NSHashTable(这可能是糟糕的设计)。因为 while(1)
循环使队列保持忙碌,自动释放池从未被耗尽,结果 PPLoginViewController
被 Foundation 保留并且从未被释放。
解决方法是将 while(1)
循环的内容放在 @autoreleasepool { }
block 中。
这方面的线索是分配报告的最后一行,它显示的是 Retain/Autorelease
而不是 Retain/Autorelease/Release
。
关于ios - 为什么我的 View Controller (从 Storyboard segue 模态呈现)在被解雇后没有被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18285560/
我有一个 aspx 应用程序。在每个 GET 中,服务器以包含除表格网格之外的所有内容的“基本”html 进行响应。 这个“网格信息”包含在页面中隐藏的输入类型(json 格式)中。 这是设计使然,无
阅读有关 iOS 中 UIViewControllers 更改的文档,我试图弄清楚呈现模态视图 Controller 之间的交互如何在自定义容器 View Controller 内工作。最终,我希望能
我正忙于编写自己的 JSF2 UIComponent 及其相关的渲染器。我所有的 UIComponent 都实现了 ClientBehaviorHolder。我不明白的是如何真正呈现 ClientBe
我正在开发一个使用UIPopoverController的应用程序,我在呈现该弹出窗口时遇到问题,我有一个添加在self.view上的UIView,并在该 View 上添加了一个表格 View ,该表
我有一个简单的应用程序,我想在用户首次登录应用程序时在其中显示一个 PageViewController。他们查看教程后,在下一次加载时不会显示 PageViewController。 但是我收到了以
我正在尝试制作一个小型的backbone.js 应用程序,但在事情的顺序上很挣扎。 在我的 html 文件中,标题中有两个脚本 block : jQuery(function(){
我有一个以模型为来源的表格: $form->setModel("test"); 在模型中,我们可以定义字段类型,例如:boolean 将在表单中制作复选框。 现在我们如何定义呈现为单选按钮的类型? 最
fabricJS 版本 2.2.3 测试 jsFiddle 我正在尝试使用 LabeledRect 子类,但我的问题是,每当我尝试从 JSON 加载它时,它都不会呈现,并且在控制台中也没有出现错误。请
在我的 Xaml 中,我定义了一个资源作为 vehicleDataInput,它提供一些文本框供用户输入数据。如果我没有为它定义一个 x:Key ,它将在我的应用程序中出现并按其应有的方式工作。问题是
我在 React 中创建了一个 Symbol 组件来轻松呈现 HTML Symbols像 euro 这样的名字将呈现 €(€) 或 sum 呈现 ∑(∑). 问题是,如果我只渲染 HTML 代码,我将
我尝试渲染一个 View ,该 View 工作正常,但似乎无法获得传递给它的模型对象。我不知道原因,因为根据所有手册和示例,这应该非常简单。 模型对象 class Race { def dis
我正在尝试为Grails项目添加一个简单功能,类似于youtube,它将允许用户喜欢/不喜欢文章。有一个非常原始的页面来显示带有喜欢的文章和一个使“喜欢”成为可能的 Controller 。 las,
我的应用程序中的第一个 ViewController 子类 UIImagePickerController 然后通过 didFinishPickingMediaWithInfo 回调,我执行以下操作:
我正在做一个简单的 redux/react todo 应用程序。我无法显示待办事项。我能够 console.log 数据,但无法显示它。我做错了什么? 我把文件分开了,这是我的app.js: impo
我正在尝试呈现一个导航 Controller ,它似乎可以工作并呈现导航 Controller 。但是,即使它有效,我仍然不断收到错误? 我的代码 let vc = storyboard.instan
我正在重新创建一个简单版本的 snapchat 应用程序,但遇到了一个恼人的小问题,我似乎无法找到解决办法。 我查看了一些答案,例如 this one但没有运气。 总体概念与 snapchat 用户单
我在呈现警报时遇到问题。我正在使用 UIAlertController。当用户按下提交按钮时,在应用程序执行某些操作时,需要立即显示“请稍候..”的警报。操作完成后,警报将消失。尽管应该在我开始执行操
我只是想用 Kinetic 渲染图像,但没有出现,也没有出现错误。 可以找到 fiddle here . 源代码: $( function() { var stage = new Kineti
我正在使用 Phantomjs 检查我的应用程序。我正在查看的页面包含很多组件,并且由 Angularjs 提供支持。我的测试服务器很慢。在 onLoadFinished 事件中,我使用渲染对网页进行
我有一个变量,它的字符串包含我所有的文档,如下所示: var string = " ReportHelloWorld"; 我想打开一个正确插入和显示此报告的新页面,但不知道如何操作。我该怎么办? 感谢
我是一名优秀的程序员,十分优秀!