溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

iOS優(yōu)化內(nèi)存,提升性能 之四

發(fā)布時間:2020-06-27 08:49:40 來源:網(wǎng)絡(luò) 閱讀:556 作者:iKingLai 欄目:移動開發(fā)

UI中顯示和隱藏view


UI中顯示和隱藏view,需要用到的內(nèi)存操作很少。但是,這個和iOS app的性能和用戶體驗有關(guān)。


當(dāng)view顯示或隱藏時,在view controller中有4個主要的方法來表示view的不同狀態(tài)。


§ viewWillAppear:在view顯示之前會調(diào)用這個方法。只有這個方法調(diào)用完之后,才會顯示你的view。為了給應(yīng)用創(chuàng)造一個很好的用戶體驗,在這里做的計算最好要非常的快。否則,用戶會感覺你的導(dǎo)航和動畫比較弱。一個好的做法是設(shè)置view的屬性(例如,背景色或文本顏色)。


例如,用戶按下返回按鈕返回到view A。但是,在view A的viewDidAppear方法內(nèi)部,有一個耗時的計算。這個計算結(jié)果可能會花幾秒鐘,但是同時UI線程會被阻塞來處理view A的內(nèi)部邏輯,同時view A也無法顯示。


  • viewDidAppear:在view顯示之后,這個方法會被調(diào)用,所以你可以把你的邏輯處理放在這里。但是,如果在它執(zhí)行完后,你的處理過程會改變view,用戶可能會感到迷惑,這不是一個好的用戶體驗。


例如,你有一個排序算法來對你的table view進行排序。當(dāng)用戶看到view A時,舊的table還在顯示。然后突然所有的的rows發(fā)生了變化,而沒有任何的警告或是解釋發(fā)生了什么事情。


  • viewDidDisappear:在view從UI消失之前會調(diào)用這個方法。任何屬于這個view的,你想要顯示給用戶的,都應(yīng)該放在這里。注意在這里你不應(yīng)該放置太多邏輯處理的代碼。如果你在這里放了很多的邏輯處理代碼,那么顯示一個新的view就會花很多時間。


沒有什么硬性規(guī)則說你應(yīng)該把邏輯處理過程放在什么地方。我向你介紹了所有的基本的概念,你可以使用他們創(chuàng)建比較好的用戶體驗和性能。



對象拷貝


你為什么需要知道對象拷貝以及為什么需要它呢?拷貝一個對象是非常有用的,如果你不想改變舊的對象,因為它可能影響到其他部分程序。在某些情況下,你根本不能修改對象,所以你只能拷貝這個對象的內(nèi)容,然后再進行修改。


淺拷貝和深拷貝


在Objective-C中,淺拷貝實際上和retaining是一樣的。因為淺拷貝是拷貝一個對象的指針到一個新的變量中,在淺拷貝和retaining之間是沒有什么不同的。


另一方面,深拷貝意味著你會實際創(chuàng)建一個新的對象,然后從舊的對象中拷貝所有的數(shù)據(jù)和實例變量到新的對象中。


為了演示淺拷貝和深拷貝在Objective-C之間的不同,考慮下面的代碼:


Shallow copying:

- (void)setMyObj:(NSObject *)newObj {

   if (newObj != myObj) {

       myObj = newObj;

   }

}

Deep copying:

- (void)setMyObj:(NSObject *)newObj {

   if (newObj != myObj) {

       myObj = [newObj copy];

   }

}


在第一種情況下,你把變量的值賦值給一個新的對象然后retain這個對象。在Objective-C中,這就是淺拷貝。在深拷貝例子中,代碼實際上拷貝了newObj的值和實例變量到myObj。


實現(xiàn)一個深拷貝


如果你確實需要一個深拷貝,你必須了解對象的整個層次結(jié)構(gòu)。

  • 你需要創(chuàng)建一個新的對象。

  • 把舊對象的所有的實例變量拷貝到新對象中。

  • 如果實例變量是基本數(shù)據(jù)類型,比如float,int或double,你只需要拷貝他們的值。Boolean不是基本類型,但是你也只需要拷貝它的值即可。

  • 對于每一個指針類型的實例變量,你同樣要拷貝它們的實例變量。

  • 這個過程需要一直持續(xù),直到結(jié)束。


這個過程可能很長,而且很難實現(xiàn)。一些內(nèi)置的對象和庫不支持深拷貝。因此,你需要在淺拷貝和深拷貝之間進行比較。例如,你不想深拷貝一個delegate,像前面介紹的,它會導(dǎo)致循環(huán)引用,即對象A擁有對象B,對象B擁有對象A。更進一步的,你通常不應(yīng)該拷貝你的delegate,因為你最終只是想要回調(diào)它,而不是創(chuàng)建它。


這是一個混合了淺拷貝和深拷貝的例子:


@interface Item : NSObject {

  1. NSString *itemName;

  2. CGFloat price;
    id delegate;

}

@property (nonatomic, copy) NSString *itemName;

@property (nonatomic, weak) CGFloat price;

@property (nonatomic, weak) id delegate;


@end


在這個例子中,你可以看到有3個實例變量。第一個是itemName(這是一個指針對象),第二個是一個基本數(shù)據(jù)類型,第三個是一個delegate。


iOS優(yōu)化內(nèi)存,提升性能 之四

如圖7-8,delegate對象在原始的item和新的item中將保持一樣。itemName對象將會被拷貝,有一個新的內(nèi)存地址(0x9124代替了0x8028),但是都有同樣的值“egg”。對于基本數(shù)據(jù)類型,例如price,將會被拷貝,它沒有內(nèi)存地址。


在對象中實現(xiàn)copy方法


為了實現(xiàn)對象的深拷貝,你通常需要重寫copyWithZone:方法。當(dāng)向一個對象發(fā)送copy消息,這個方法會被調(diào)用。這里有一些重寫這個方法的代碼。你需要用alloc和init創(chuàng)建一個新的對象,然后使用set方法給實例變量設(shè)值。


- (id)copyWithZone:(NSZone *)zone {
   Item *copy = [[Item allocWithZone: zone] initWithName:self.itemName];

   copy.price = self.price;
   copy.delegate = self.delegate;
   return copy;

}


就像前面所說的,在你的item class中如果有自定義的實例變量,你需要為它實現(xiàn)copy方法。在我的例子中,為了簡單起見,代碼沒有創(chuàng)建一個新的itemName對象。







向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI