2011-06-02 95 views
0

嗯,我仍然對目標C屬性和實例變量感到困惑。 我在viewDidLoad中創建了一個LocationManager對象。一方面LocationMan只是一個實例變量,另一方面它被聲明爲一個屬性。看看例子:Iphone - 分配屬性和實例變量

第一個例子:

頁眉:

CLLocationManager* _locationMan; 

實現:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease]; 
_locationMan = theManager; 
_locationMan.delegate = self; 

第二個例子

他阿德:

CLLocationManager* _locationMan; 
@property (retain, nonatomic) CLLocationManager* locationMan; 

實現:

self.locationMan = [[[CLLocationManager alloc] init] autorelease]; 
self.locationMan.delegate = self; 

請告訴我只是使用的是第二個工作,第一個不這些實施例之間的差異?內存管理髮生了什麼?

回答

3

你在你的第一個例子有問題:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease]; 

通過使用autorelease造成的。 autorelease可以看作是含義:在不久的將來某個時刻,release會自動將這個對象。考慮到autorelease的實現方式,通過釋放池實現,這通常發生在控制流下次返回到主循環並釋放池被清空時。

因此,在您的第一個案例中,您將創建對象並將其存儲在您的ivar中;但很快它就會被釋放,並且由於您沒有明確地將其保留在其他地方,它最終將被釋放。當你之後訪問它時,你會得到錯誤。如果你沒有使用autorelease,一切會正常工作:

CLLocationManager* theManager = [[CLLocationManager alloc] init]; //-- this is correct 
_locationMan = theManager; //-- because you assign directly to the ivar 

在你的第二個例子,創作是一樣的,這意味着,該對象也將被標記爲自動釋放。但是,在這種情況下,您將其分配給獲得retain修飾符的屬性。這意味着該對象將在分配給屬性時自動保留。所以,當autorelease實際上完成時(當你回到主要外觀,大致),你的對象將已經有它的保留計數增加1;那麼自動釋放它不會使其保留計數變爲0,並且該對象不會被釋放。

你必須清楚的知道那是什麼:

  1. alloc將設置保留計數爲1;

  2. retain屬性將在分配給它們時遞增保留計數;

  3. autorelease就像緩釋,使平均時間(之前的版本實際上是完成的,這意味着你的方法和呼叫者的調養主循環),你可以放心,之後使用對象它將被釋放。

+0

明白了。非常感謝你。 – shadowhorst 2011-06-02 14:28:58

0

在第一個例子中,你沒有經歷合成的setter,它負責保留對象。在這種情況下,當theManager被自動回收時,_locationManager不會持有任何東西,因此theManager得到處理。

第二種情況使用合成的setter(因爲它通過self調用它),所以它在自動發佈後保留theManager

1

我標記了代碼中保留的更改,也許它會變得更加清晰。

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease]; 
                ^^^^^ + 1 ^^^^^^^^^^^ - 1 = 0 
_locationMan = theManager; 

當您的保留降到0時,對象不再存在。下次嘗試訪問它時,應用程序崩潰。由於autorelease,這會發生在您的autorelease池被耗盡之後,在您離開當前方法後的將來未知點。


self.locationMan = [[[CLLocationManager alloc] init] autorelease]; 
    ^+ 1        ^^^^^ + 1 ^^^^^^^^^^^ - 1 = +1 

你仍然保留的對象。您必須稍後才能發佈它,但您可以毫無問題地訪問它。

+0

謝謝。所以區別在於屬性生成的訪問器方法。使用setter方法會增加保留計數。非常感謝你的好解釋。 – shadowhorst 2011-06-02 14:26:43