+ (UIView *)getView
{
UIView *view = [[UIView alloc] init];
return view;
}
- (UIView *)getView
{
UIView *view = [[UIView alloc] init];
return view;
}
- (void)viewDidLoad {
[super viewDidLoad];
__weak UIView *view1 = [self getView];
__weak UIView *view2 = [SampleViewController getView];
NSLog(@"%@, %@", view1, view2); // view1 is null and view2 isn't null
for (int i = 0; i < 1000; i++) { // Wait
NSLog(@"Waiting");
}
NSLog(@"%@, %@", view1, view2); // view1 is null and view2 isn't null
}
我在viewDidLoad中测试它,它显示view1为null并且view2具有值
答案 0 :(得分:1)
它们都被释放但是静态的稍后。
尝试添加更多代码:
NSLog(@"%@, %@", view1, view2); // You already have this
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@, %@", view1, view2);
});
第二次打印将在3秒后发生,并且应该显示两者都为空。
这很可能是非静态方法的编译优化,它不会在您的视图上使用自动释放池。静态的一个显然位于自动释放池中,并将在下一个运行循环中释放。
编辑:我在创建新项目后测试的完整代码:
@implementation ViewController
+ (UIView *)getView
{
UIView *view = [[UIView alloc] init];
return view;
}
- (UIView *)getView
{
UIView *view = [[UIView alloc] init];
return view;
}
- (void)viewDidLoad {
[super viewDidLoad];
__weak UIView *view1 = [self getView];
__weak UIView *view2 = [ViewController getView];
NSLog(@"%@, %@", view1, view2);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@, %@", view1, view2);
});
}
@end
更进一步:
我创建了一个视图子类,以便能够进行更多调试:
@interface MyView: UIView
@end
@implementation MyView
- (void)dealloc {
NSLog(@"Deallocated");
}
@end
那么我们就有了:
+ (UIView *)getView
{
UIView *view = [[MyView alloc] init];
return view;
}
- (UIView *)getView
{
UIView *view = [[MyView alloc] init];
return view;
}
我放了一个dealloc方法,所以我可以设置一个断点init。第一个命中是viewDidLoad
,例如被称为对象。这样就可以清楚地知道这个对象没有进行自动释放,但是ARC系统自动添加了[view release]
。第二个电话就在它之后,并说它来自自动释放池。
答案 1 :(得分:0)
由于未知原因,编译器为DEBUG中的类方法添加了__autoreleasing
属性作为返回指针。我认为这很糟糕,因为它可能导致发布中的不同行为。您应该向Apple报告此错误。
答案 2 :(得分:0)
+ (UIView *)getView
{
UIView *view = [[MyView alloc] init];
return view;
}
- (UIView *)getView
{
UIView *view = [[MyView alloc] init];
return view;
}
- (void)viewDidLoad {
[super viewDidLoad];
__weak UIView *view1;
__weak UIView *view2;
@autoreleasepool{
view1 = [self getView];
view2 = [SampleViewController getView];
NSLog(@"%@ %@", view1, view2);
};
}
view1和view2都有值。 autorelease-object将被添加到最近的自动释放池中,因此instance-method也使用autorelease。编译器可能会添加class-method返回的对象和instance-method在不同的autorelease-pool中返回的对象。