您好,登錄后才能下訂單哦!
在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 {
NSString *itemName;
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。
如圖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對象。
免責(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)容。