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

我有一个UIViewController有一个IBOutlet UILabel标签连接在XIB。

 #import <Foundation/Foundation.h> @interface MyViewController : UIViewController { IBOutlet UILabel *aLabel; } @end 

根据iOS编程:大书呆子牧场指南(第2版)第7章

当[MyViewController]重新加载其视图时,将从XIB文件创build一个新的UILabel实例。

因此,build议在viewDidUnload释放标签。

 - (void)viewDidUnload { [super viewDidUnload]; [aLabel release]; aLabel = nil; } 

作为一个C#程序员,我已经把它鼓起来了,把nil / null分配给事物是毫无意义的。 虽然我可以看到它在Objective-C中更有意义,但它仍然略微提高了我的代码审美感。 我删除它,一切工作正常。

但是,当我试图用MKMapView做类似的事情时,试图加载NIB的应用程序错误EXC_BAD_ACCESS

 #import <Foundation/Foundation.h> @interface MyViewController : UIViewController { IBOutlet MKMapView *mapView; } @end 

 - (void)viewDidUnload { [super viewDidUnload]; [mapView release]; mapView = nil; // Without this line an exception is thrown. } 

为什么mapView没有设置nil时出现错误,但是当aLabel没有设置nil时没有出现aLabel

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


事实certificate,我只是对aLabel没有被引用的aLabel错误。 不知道是什么让我觉得它不是。

然而,这仍然留下了为什么在NIB被加载时被引用的问题。

当设置字段或属性时,释放消息被发送到旧值(合成属性集合方法发送释放消息,或setValue:forKey:如果是字段则发送消息)。 由于旧值已被释放,因此会导致EXC_BAD_ACCESS

这是因为内存pipe理,特别是垃圾收集的缺乏。

在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上调用一个消息,没有任何反应。 所以如果每次你完成一个对象并调用释放它,你也应该将它设置nil – 这意味着如果你再次使用该指针,它不会崩溃!

当设备收到内存警告时,通常会调用viewDidUnload

在视图堆栈中,可能会出现设备可以通过释放未使用的对象来释放内存的情况。 想象一下,你有一个导航堆栈与一些视图控制器。 堆栈中较低的接口视图控制器不可访问,但仍在使用内存。 所以通常是一个好主意,将任何无法访问的界面元素都清空。 这些将在需要的时候重新加载viewDidLoad。

通常在ViewDidUnload您应该释放从Nib文件创build或在ViewDidLoad方法中分配的所有视图对象

你的mapView抛出一个exception,因为你的视图控制器试图访问MapView但是mapView已经被释放。 当您将sockets设置为零时,任何发送给它的消息都将被忽略。