Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 为什么在viewDidUnload中将nil分配给IBOutlets?_Iphone_Objective C_Ios_Cocoa Touch_Uikit - Fatal编程技术网

Iphone 为什么在viewDidUnload中将nil分配给IBOutlets?

Iphone 为什么在viewDidUnload中将nil分配给IBOutlets?,iphone,objective-c,ios,cocoa-touch,uikit,Iphone,Objective C,Ios,Cocoa Touch,Uikit,我有一个UIViewController,它有一个IBOutlet,用于UILabel,标签连接在XIB中 #import <Foundation/Foundation.h> @interface MyViewController : UIViewController { IBOutlet UILabel *aLabel; } @end 作为一名C#程序员,我有一种强烈的感觉,那就是为事物指定nil/null是毫无意义的。虽然我可以看出Objective-C更具意义,但

我有一个
UIViewController
,它有一个
IBOutlet
,用于
UILabel
,标签连接在XIB中

#import <Foundation/Foundation.h>

@interface MyViewController : UIViewController {
    IBOutlet UILabel *aLabel; 
}
@end
作为一名C#程序员,我有一种强烈的感觉,那就是为事物指定nil/null是毫无意义的。虽然我可以看出Objective-C更具意义,但它仍然略微削弱了我的代码美学感*。我把它取了下来,一切都很好

但是,当我尝试使用
MKMapView
执行类似操作时,在尝试加载NIB时出现了应用程序错误
EXC_BAD_ACCESS

#import <Foundation/Foundation.h>

@interface MyViewController : UIViewController {
    IBOutlet MKMapView *mapView;
}
@end
为什么当
mapView
未设置为
nil
时会出现错误,而当
aLabel
未设置为
nil
时不会出现错误

*我意识到我需要调整我对新语言的代码审美感,但这需要时间


事实证明,我完全错了,
aLabel
没有被引用。不知道是什么让我觉得不是

然而,这仍然留下了一个问题,即为什么在加载NIB时引用它们


设置字段或属性时,将向旧值发送释放消息(合成属性集方法发送释放消息,或者
setValue:forKey:
发送消息(如果是字段)。由于旧值已被释放,这将导致
EXC\u BAD\u ACCESS

viewDidUnload
通常在设备收到内存警告时调用

在视图堆栈中,可能存在设备可以通过释放未使用的对象来释放内存的情况。假设您有一个带有多个视图控制器的导航堆栈。堆栈下部的界面视图控制器不可访问,但仍在使用内存。因此,消除任何无法访问的接口元素通常是一个好主意。然后在需要时使用viewDidLoad重新加载这些文件

通常在
ViewDidLoad
中,您应该释放从Nib文件创建的或在
ViewDidLoad
方法中分配的任何视图对象


您的
mapView
正在引发异常,因为您的视图控制器正在尝试访问
mapView
,但
mapView
已被释放。当您将出口设置为nil时,发送给它的任何消息都将被忽略。

这是因为内存管理,特别是缺少垃圾收集

在C#(如您所知)中,不再在作用域中的对象将被删除。在objective-c中,这不会发生。您必须依靠“保留/释放”来告知对象何时完成操作

mapView bug显示的objective-c引用计数方法有一个缺点。对对象调用
release
,可能会导致该对象被解除分配。但是,指向对象的指针仍将指向同一个位置-对象将不再存在

比如说

// We create an object.
MyObject *object = [[MyObject alloc] init];

// At this point, `object` points to the memory location of a MyObject instance
// (the one we created earlier). We can output that if we want :
NSLog(@"0x%08X", (int)myObject);

// You should see a number appear in the console - that's the memory address that
// myObject points to.
// It should look something like 0x8f3e4f04

// What happens if we release myObject?
[myObject release];

// Now, myObject no longer exists - it's been deallocated and it's memory has been
// marked as free

// The myObject pointer doesn't know that it's gone - see :
NSLog(@"0x%08X", (int)myObject);

// This outputs the same number as before. However, if we call a method on myObject
// it will crash :
NSLog(@"%@", myObject);

在objective-c中,如果您尝试在
nil
上调用消息,则不会发生任何事情。因此,如果每次处理完一个对象并调用release,还应该将其设置为
nil
——这意味着如果再次尝试使用该指针,它不会崩溃

当我切换到控制器的视图时,在调用控制器的任何方法之前抛出异常。所以我的问题是,什么东西试图访问
mapView
而不是试图访问
aLabel
?根据我对前面答案的回答,我的问题是什么东西试图访问
mapView
,而不是试图访问
aLabel
?但事实上,如果有东西试图访问一个已经释放/解除分配的对象,我认为这仍然是一个糟糕的设计。正确的设计(这并不意味着将释放的对象设置为零)应该确保不会发生这种情况。@Rudy Velthuis这是防御:)你不知道你正在使用的apple框架/库中是否有bug-他们可能会尝试自己调用该对象,因此将其设置为
nil
将保护你的代码不受其他错误的影响。(并不是说我不同意这是一个糟糕的设计!)@ICR你怎么知道没有任何东西访问你的标签-仅仅因为内存被释放并不意味着它被其他任何东西使用-也许标签被访问的方式不会导致崩溃;)@迪恩沃姆伯恩:对不起,这不是“防御编程”,而是“偏执编程”。更新时出现了错误。从iOS 6.0开始,viewDidUnload被折旧。在内存不足的情况下不再清除视图,因此永远不会调用此方法。
- (void)viewDidUnload {
    [super viewDidUnload];
    [mapView release];
    mapView = nil; // Without this line an exception is thrown.
}
// We create an object.
MyObject *object = [[MyObject alloc] init];

// At this point, `object` points to the memory location of a MyObject instance
// (the one we created earlier). We can output that if we want :
NSLog(@"0x%08X", (int)myObject);

// You should see a number appear in the console - that's the memory address that
// myObject points to.
// It should look something like 0x8f3e4f04

// What happens if we release myObject?
[myObject release];

// Now, myObject no longer exists - it's been deallocated and it's memory has been
// marked as free

// The myObject pointer doesn't know that it's gone - see :
NSLog(@"0x%08X", (int)myObject);

// This outputs the same number as before. However, if we call a method on myObject
// it will crash :
NSLog(@"%@", myObject);