1. 程式人生 > >iOS開發中 new與alloc/init的區別 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的區別

iOS開發中 new與alloc/init的區別 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的區別

專案過程中,想到這幾個概念的區別有些模糊,於是縱觀各種資料,來篇博文為自己記錄下,也為小夥伴們說說我的理解。

[className new] 和 [[className alloc] init] 的區別

1.在實際開發中很少會用到new,一般建立物件咱們看到的全是[[className alloc] init]

但是並不意味著你不會接觸到new,在一些程式碼中還是會看到[[className alloc] init]

還有去面試的時候,也很可能被問到這個問題。

2.那麼,他們兩者之間到底有什麼區別呢

我們看原始碼:

  1. new
  2. id newObject = (*_alloc)((Class)self, 0); 
  3. Class metaClass = self->isa; 
  4. if (class_getVersion(metaClass) > 1) 
  5. return [newObject init]; 
  6. else
  7. return newObject; 
  8. //而 alloc/init 像這樣:
  9. + alloc 
  10. return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  
  11. - init 
  12. return self; 

通過原始碼中我們發現,[className new]基本等同於[[className alloc] init]

區別只在於alloc分配記憶體的時候使用了zone.

這個zone是個什麼東東呢?

它是給物件分配記憶體的時候,把關聯的物件分配到一個相鄰的記憶體區域內,以便於呼叫時消耗很少的代價,提升了程式處理速度;

3.而為什麼不推薦使用new?

不知大家發現了沒有:如果使用new的話,初始化方法被固定死只能呼叫init.

而你想呼叫initXXX怎麼辦?沒門兒!據說最初的設計是完全借鑑Smalltalk語法來的。

傳說那個時候已經有allocFromZone:這個方法,

但是這個方法需要傳個引數id myCompanion = [[TheClass allocFromZone:[self zone]] init];

這個方法像下面這樣:

  1. + allocFromZone:(
    void *) z 
  2. return (*_zoneAlloc)((Class)self, 0, z);  
  3. //後來簡化為下面這個:
  4. + alloc 
  5. return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  

但是,出現個問題:這個方法只是給物件分配了記憶體,並沒有初始化例項變數。

是不是又回到new那樣的處理方式:在方法內部隱式呼叫init方法呢?

後來發現“顯示呼叫總比隱式呼叫要好”,所以後來就把兩個方法分開了。

概括來說,new和alloc/init在功能上幾乎是一致的,分配記憶體並完成初始化。

差別在於,採用new的方式只能採用預設的init方法完成初始化,

採用alloc的方式可以用其他定製的初始化方法。

再來說一個突然想起來的問題:[NSArray array] [[NSArray alloc]init] (包括字典等同類) 的使用方法的區別:

alloc (記憶體分配)以及init(初始化) Objective-C 協議分為非正式協議和正式協議 .

這兩個方式都是建立一個空的Array
[NSArray array]不需要release,使用autoreleasepool機制。
[[NSArray alloc] init]需要自己手動release


專案使用崩潰例項:


在ViewDidLoad中   
jsonDataDic = [NSMutableDictionary dictionary];    
[self jsonParse];
建立一個空字典,在jsonParse中使用了這個詞典,導致程式崩潰
解決方法:在jsonDataDic前面加上self.即可
原因:不加的話,指標的作用域僅在ViewDidLoad中,進入jsonParse後該指標已釋放,成為了一個野指標,再對其進行操作,使程式崩潰。
注意:字典是沒有順序的,字典的allkeys或者allvalues存放到陣列中是隨機的。

總結:


new做的事情和alloc init是一樣的,當然你要構造方法是init的時候完全可以用new來代替 ,alloc 不僅僅可以使用init構造方法,更可以自定義構造方法e.g initWithFrame等等。
另外,alloc開闢空間後能夠自動清空新開闢記憶體空間中的老資料,不會出現莫名奇妙的錯誤,見《Objective-C基礎教程》

說到這個問題,可能有小夥伴又懵了,那self. _有什麼區別呢,再說下這兩個 :

( - -!沒完了)

self.programStack等於[self programStack],會走你的懶載入方法;而_programStack類似於self->_programStack。

用self點出屬性是更好的選擇,因為這樣可以相容懶載入,同時也避免了使用下劃線的時候忽視了self這個指標,後者容易在block中造成迴圈引用。

科普:懶載入(Load On Demand)是一種獨特而又強大的資料獲取方法,它能夠在使用者滾動頁面的時候自動獲取更多的資料,而新得到的資料不會影響原有資料的顯示,同時最大程度上減少伺服器端的資源耗用。

這兩種使用方式顯然是不一樣的。

主要是涉及到記憶體管理的問題。self.propertyName 使用self. 是對屬性的訪問。使用_ 是對區域性變數的訪問。
所有被宣告為屬性的成員,在ios5 之前需要使用編譯器指令@synthesize 來告訴編譯器幫助生成屬性的getter,setter方法。之後這個指令可以不用人為指定了,預設情況下編譯器會幫我們生成。 編譯器在生成getter,setter方法時是有優先順序的,它首先查詢當前的類中使用者是否已定義屬性的getter,setter方法,如果有,則編譯器會跳過,不會再生成,使用使用者定義的方法。 也就是說你在使用self.propertyName 時是在呼叫一個方法。

_______________________________________________________哥哥愛開發_________________________________________________________________

本篇博文有查詢資料中大神的理論引用,有自己的原創理解,只為整理在一起方便理解。

最後:開發,只為簡單生活,技術改變世界!~yeah~

相關推薦

iOS開發 newalloc/init區別 [NSArray array] [[NSArray alloc]init] self. _區別

專案過程中,想到這幾個概念的區別有些模糊,於是縱觀各種資料,來篇博文為自己記錄下,也為小夥伴們說說我的理解。 [className new] 和 [[className alloc] init] 的區別 1.在實際開發中很少會用到new,一般建立物件咱們看到的全

iOS開發地圖定位

視圖 編寫 aps 簡單 -a 第三方 span spa margin   不管是QQ還是微信的移動client都少不了定位功能,之前在微信demo中沒有加入定位功能,今天就寫個定位的小demo來了解一下定位和地圖的東西。地圖和定位看上去是挺高大上一東西。其有使用方法比

iOS 開發null 的處理

原文連結:http://www.jianshu.com/p/a73aab1c1422 針對(null)這種情況,將一個字串賦值為nil,列印輸出結果就是(null)那麼湧入下來做判斷if(result==nil) {      NSLog(@"執行"); } 針對<null>的情況 f([r

iOS 開發OC JS的互動

iOS原生應用和web頁面的互動有iOS7之後的JavaScriptCore、攔截協議、第三方框架WebViewJavaScriptBridge、iOS8之後的WKWebView幾種方法,這一章我們主要講解JavaScriptCore和攔截協議這兩種辦法。WebViewJ

iOS開發知識之:iOS開發allocnew區別

1.在實際開發中很少會用到new,一般建立物件咱們看到的全是[[className alloc] init] 但是並不意味著你不會接觸到new,在一些程式碼中還是會看到[className new], 還有去面試的時候,也很可能被問到這個問題。 2.那麼,他們兩者之間到底有什麼區別呢 我們看原始碼:

ios開發類方法例項方法區別 以及self有什麼不同

Objective-C裡面既有例項方法也類方法。類方法(Class Method) 有時被稱為工廠方法(Factory Method)或者方便方法(Convenience method)。工廠方法的稱謂明顯和一般意義上的工廠方法不同,從本質上來說,類方法可以獨立於物件而執行,所以在其他的語言裡面類方法有的

IOS開發之——objectForKeyvalueForKey在NSDictionary的差異

什麽 iat app 報錯信息 lease 方法 去掉 defined atom 從 NSDictionary 取值的時候有兩個方法,objectForKey: 和 valueForKey:,這兩個方法具體有什麽不同呢? 先從 NSDictionary 文檔中來看這兩個方法

iOS開發的position+anchorPointframe應用解釋

移動 pos 限制 一起 frame -1 必須 posit 解釋 我剛開始時非常困惑這兩個地方, 所以現在好好解釋一下他們的聯系. 1/ position與anchorPoint是一對屬性, 經常一起設置來確定控件的位置 frame單獨設置 2/ position

iOS開發之OCswift開發混編教程,代理的相互呼叫,block的實現。OC呼叫Swift的代理, OC呼叫Swift的Block 閉包

  本文章將從兩個方向分別介紹 OC 與 swift 混編   1. 第一個方向從 swift工程 中引入 oc類    1. 1 如何在swift的類中使用oc類    1.2  如何在swift中實現oc的代理方法  &

敏捷開發之Scrum掃盲,敏捷開發XPSCRUM的區別

現在敏捷開發是越來越火了,人人都在談敏捷,人人都在學習Scrum和XP... 為了不落後他人,於是我也開始學習Scrum,今天主要是對我最近閱讀的相關資料,根據自己的理解,用自己的話來講述Scrum中的各個環節,主要目的有兩個,一個是進行知識的總結,另外一個是覺得網上很多學習資料的講述方式讓初學者不太容易

移動端開發iOS系統 new Date() 返回 NaN 的問題

問題:   通過 new Date() 函式將後臺返回的時間('2021-11-25')獲取時間戳。在 chrome 瀏覽器中沒有出現問題,但在 iPhone 真機測試的時候,顯示的結果不符合預期。通過除錯發現 iOS 中 new Date('2021-11-25') 返回的結果是 NaN,問題出現的原因是

iOS開發Block的理解使用

// 隨機生成的顏色 UIColor *color = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1]; // 第二步 給Blo

iOS開發各種關鍵字的區別

1.一些概念 1.淺Copy:指標的複製,只是多了一個指向這塊記憶體的指標,共用一塊記憶體。 深Copy:記憶體的複製,兩塊記憶體是完全不同的, 也就是兩個物件指標分別指向不同的記憶體,互不干涉。 2.atomic是Objc使用的一種執行緒保護技術, 基本上來講

Android開發佈局元件(二)—— padding margin 的區別

在 Android開發中我們會設定某個檢視相對於別的檢視的距離,這時我們就要用到 margin 和 padding ,但是有時候很容易把這兩個屬性弄混淆,那我們就看看他們的區別。 外邊距(margin): 屬於佈局引數,決定兩個元件之間的距離。作用於多個元件之間。 內邊距(

iOS開發之OCswift開發混編教程,代理的相互呼叫,block的實現。OC呼叫Swift的代理, OC呼叫Swift的Block 閉包,swift 3.0

最新一些學妹問起,所以抽點時間來寫的,適合入門級別的swift 與 OC 混編 的程式猿。   本文章將從兩個方向分別介紹 OC 與 swift 混編   1. 第一個方向從 swift工程 中引入 oc類      1. 1 如何在swift的類中使用oc類     1

iOS開發(null)的處理

補充一個知識 NULL nil Nil NSNull的去唄 標識 值 含義 NULL (void *)0 C指標的字面零值 nil

iOS開發同時識別旋轉縮放手勢

今天我在使用UIRotationGestureRecognizer和UIPinchGestureRecognizer時,發現它們在預設情況下不能同時被識別。而且在真機操作時,經常發生只識別縮放,難以識別旋轉的情況。所以將它們設為能同時識別是非常有必要的。 經過

iOS開發之swiftOC混編出現的坑,oc不能對swift的代理進行呼叫,不能訪問swift的代理,swift的回撥方法

1. swift與oc混編譯具體怎麼實現,這兒我就不重複講出了,網上有大把的人講解。 2. 在swift與OC混編的編譯環境下, oc類不能訪問swift建立類中的代理? 解決方法如下: 在代理的頭部加上 @objc(代理名字),這樣就在外部就可以訪問了,如下圖。 然

iOS開發時OCC的混編,strcpy導致的記憶體溢位、野指標

在最近的專案開發中,由於需要使用C語言的演算法供給OC專案呼叫,所以研究了一下OC與C的混編及.a庫的相關生成。而在混編的過程中,C語言的演算法都能正常呼叫了,但是被一個問題困擾了很長一段時間,就是在

兩張圖看懂Android開發MVCMVP的區別

看了很多文章,沒有很好的文章能簡明扼要的說清楚Android開發中MVC和MVP的區別。MVC很早就出來了,之前廣泛用於JavaWeb開發中,MVC也可以用來開發Android,但是有些水土不服! 1、MVC結構示意圖 2、MVP結構示意圖