偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

大牛說(shuō):這是不可錯(cuò)過(guò)的iOS開(kāi)發(fā)技巧(二)

移動(dòng)開(kāi)發(fā) iOS
通常要想創(chuàng)建一個(gè)特殊效果(如blur效果),可以創(chuàng)建一個(gè)UIVisualEffectView視圖對(duì)象,這個(gè)對(duì)象提供了一種簡(jiǎn)單的方式來(lái)實(shí)現(xiàn)復(fù)雜的視覺(jué)效果。

換了個(gè)廠子,還不到1個(gè)月。哎,著實(shí)是累啊,基本上是996.5的節(jié)奏,只會(huì)更多。加班把我快加吐了,但人在江湖,身不由已啊。為了討口飯吃,命也不要了。誰(shuí)讓咱只是個(gè)臭寫代碼的呢。不過(guò)加班是多,只是長(zhǎng)得太丑,所有沒(méi)辦法,沒(méi)時(shí)間也得抽時(shí)間來(lái)學(xué)習(xí)。不然,飯都沒(méi)得吃了,還得養(yǎng)家糊口呢。

本期總結(jié)的內(nèi)容不是很多,主要有以下幾個(gè)問(wèn)題:

  • 使用UIVisualEffectView為視圖添加特殊效果
  • Nullability Annotations
  • weak的生命周期

使用UIVisualEffectView為視圖添加特殊效果

在iOS 8后,蘋果開(kāi)放了不少創(chuàng)建特效的接口,其中就包括創(chuàng)建毛玻璃(blur)的接口。

通常要想創(chuàng)建一個(gè)特殊效果(如blur效果),可以創(chuàng)建一個(gè)UIVisualEffectView視圖對(duì)象,這個(gè)對(duì)象提供了一種簡(jiǎn)單的方式來(lái)實(shí)現(xiàn)復(fù)雜的視覺(jué)效果。這個(gè)可以把這個(gè)對(duì)象看作是效果的一個(gè)容器,實(shí)際的效果會(huì)影響到該視圖對(duì)象底下的內(nèi)容,或者是添加到該視圖對(duì)象的contentView中的內(nèi)容。

我們舉個(gè)例子來(lái)看看如果使用UIVisualEffectView:

  1. let bgView: UIImageView = UIImageView(image: UIImage(named: "visual")) 
  2. bgView.frame = self.view.bounds 
  3. self.view.addSubview(bgView) 
  4.  
  5. let blurEffect: UIBlurEffect = UIBlurEffect(style: .Light) 
  6. let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect) 
  7. blurView.frame = CGRectMake(50.050.0, self.view.frame.width - 100.0200.0
  8. self.view.addSubview(blurView) 

這段代碼是在當(dāng)前視圖控制器上添加了一個(gè)UIImageView作為背景圖。

我們可以看到UIVisualEffectView還是非常簡(jiǎn)單的。需要注意是的,不應(yīng)該直接添加子視圖到UIVisualEffectView視圖中,而是應(yīng)該添加到UIVisualEffectView對(duì)象的contentView中。

另外,盡量避免將UIVisualEffectView對(duì)象的alpha值設(shè)置為小于1.0的值,因?yàn)閯?chuàng)建半透明的視圖會(huì)導(dǎo)致系統(tǒng)在離屏渲染時(shí)去對(duì)UIVisualEffectView對(duì)象及所有的相關(guān)的子視圖做混合操作。這不但消耗CPU/GPU,也可能會(huì)導(dǎo)致許多效果顯示不正確或者根本不顯示。

我們?cè)谏厦婵吹?,初始化一個(gè)UIVisualEffectView對(duì)象的方法是UIVisualEffectView(effect: blurEffect),其定義如下:

  1. init(effect effect: UIVisualEffect) 

這個(gè)方法的參數(shù)是一個(gè)UIVisualEffect對(duì)象。我們查看官方文檔,可以看到在UIKit中,定義了幾個(gè)專門用來(lái)創(chuàng)建視覺(jué)特效的,它們分別是UIVisualEffect、UIBlurEffect和UIVibrancyEffect。它們的繼承層次如下所示:

  1. NSObject 
  2. | -- UIVisualEffect 
  3. | -- UIBlurEffect 
  4. | -- UIVibrancyEffect 

UIVisualEffect是一個(gè)繼承自NSObject的創(chuàng)建視覺(jué)效果的基類,然而這個(gè)類除了繼承自NSObject的屬性和方法外,沒(méi)有提供任何新的屬性和方法。其主要目的是用于初始化UIVisualEffectView,在這個(gè)初始化方法中可以傳入U(xiǎn)IBlurEffect或者UIVibrancyEffect對(duì)象。

一個(gè)UIBlurEffect對(duì)象用于將blur(毛玻璃)效果應(yīng)用于UIVisualEffectView視圖下面的內(nèi)容。如上面的示例所示。不過(guò),這個(gè)對(duì)象的效果并不影響UIVisualEffectView對(duì)象的contentView中的內(nèi)容。

UIBlurEffect主要定義了三種效果,這些效果由枚舉UIBlurEffectStyle來(lái)確定,該枚舉的定義如下:

  1. enum UIBlurEffectStyle : Int { 
  2. case ExtraLight 
  3. case Light 
  4. case Dark 

其主要是根據(jù)色調(diào)(hue)來(lái)確定特效視圖與底部視圖的混合。

與UIBlurEffect不同的是,UIVibrancyEffect主要用于放大和調(diào)整UIVisualEffectView視圖下面的內(nèi)容的顏色,同時(shí)讓UIVisualEffectView的contentView中的內(nèi)容看起來(lái)更加生動(dòng)。通常UIVibrancyEffect對(duì)象是與UIBlurEffect一起使用,主要用于處理在UIBlurEffect特效上的一些顯示效果。接上面的代碼,我們看看在blur的視圖上添加一些新的特效,如下代碼所示:

  1. let vibrancyView: UIVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect)) 
  2. vibrancyView.setTranslatesAutoresizingMaskIntoConstraints(false
  3. blurView.contentView.addSubview(vibrancyView) 
  4.  
  5. var label: UILabel = UILabel() 
  6. label.setTranslatesAutoresizingMaskIntoConstraints(false
  7. label.text = "Vibrancy Effect" 
  8. label.font = UIFont(name: "HelveticaNeue-Bold", size: 30
  9. label.textAlignment = .Center 
  10. label.textColor = UIColor.whiteColor() 
  11. vibrancyView.contentView.addSubview(label)

     

vibrancy特效是取決于顏色值的。所有添加到contentView的子視圖都必須實(shí)現(xiàn)tintColorDidChange方法并更新自己。需要注意的是,我們使用UIVibrancyEffect(forBlurEffect:)方法創(chuàng)建UIVibrancyEffect時(shí),參數(shù)blurEffect必須是我們想加效果的那個(gè)blurEffect,否則可能不是我們想要的效果。

另外,UIVibrancyEffect還提供了一個(gè)類方法notificationCenterVibrancyEffect,其聲明如下:

class func notificationCenterVibrancyEffect() -> UIVibrancyEffect!

這個(gè)方法創(chuàng)建一個(gè)用于通知中心的Today擴(kuò)展的vibrancy特效。

參考

UIVisualEffectView Class Reference

UIVisualEffect Class Reference

 

UIBlurEffect Class Reference

 

UIVibrancyEffect Class Reference UIVisualEffect – Swift Tutorial iOS 8: UIVisualEffect

Pointer is missing a nullability type specifier (nonnull or nullable)問(wèn)題的處理 — Nullability Annotations

最近在用Xcode 6.3寫代碼,一些涉及到對(duì)象的代碼會(huì)報(bào)如下編譯器警告:

  1. Pointer is missing a nullability type specifier (__nonnull or __nullable) 

于是google了一下,發(fā)現(xiàn)這是Xcode 6.3的一個(gè)新特性,即nullability annotations。

#p#

Nullability Annotations

我們都知道在swift中,可以使用!和?來(lái)表示一個(gè)對(duì)象是optional的還是non-optional,如view?和view!。而在Objective-C中則沒(méi)有這一區(qū)分,view即可表示這個(gè)對(duì)象是optional,也可表示是non-optioanl。這樣就會(huì)造成一個(gè)問(wèn)題:在Swift與Objective-C混編時(shí),Swift編譯器并不知道一個(gè)Objective-C對(duì)象到底是optional還是non-optional,因此這種情況下編譯器會(huì)隱式地將Objective-C的對(duì)象當(dāng)成是non-optional。

為了解決這個(gè)問(wèn)題,蘋果在Xcode 6.3引入了一個(gè)Objective-C的新特性:nullability annotations。這一新特性的核心是兩個(gè)新的類型注釋:__nullable和__nonnull。從字面上我們可以猜到,__nullable表示對(duì)象可以是NULL或nil,而__nonnull表示對(duì)象不應(yīng)該為空。當(dāng)我們不遵循這一規(guī)則時(shí),編譯器就會(huì)給出警告。

我們來(lái)看看以下的實(shí)例,

  1. @interface TestNullabilityClass () 
  2.  
  3. @property (nonatomic, copy) NSArray * items; 
  4.  
  5. - (id)itemWithName:(NSString * __nonnull)name; 
  6.  
  7. @end 
  8.  
  9. @implementation TestNullabilityClass 
  10.  
  11. ... 
  12.  
  13. - (void)testNullability { 
  14.  
  15. [self itemWithName:nil]; // 編譯器警告:Null passed to a callee that requires a non-null argument 
  16.  
  17. - (id)itemWithName:(NSString * __nonnull)name { 
  18. return nil; 
  19.  
  20. @end 

不過(guò)這只是一個(gè)警告,程序還是能編譯通過(guò)并運(yùn)行。

事實(shí)上,在任何可以使用const關(guān)鍵字的地方都可以使用__nullable和__nonnull,不過(guò)這兩個(gè)關(guān)鍵字僅限于使用在指針類型上。而在方法的聲明中,我們還可以使用不帶下劃線的nullable和nonnull,如下所示:

  1. - (nullable id)itemWithName:(NSString * nonnull)name 

在屬性聲明中,也增加了兩個(gè)相應(yīng)的特性,因此上例中的items屬性可以如下聲明:

  1. @property (nonatomic, copy, nonnull) NSArray * items; 

當(dāng)然也可以用以下這種方式:

  1. @property (nonatomic, copy) NSArray * __nonnull items; 

推薦使用nonnull這種方式,這樣可以讓屬性聲明看起來(lái)更清晰。

Nonnull區(qū)域設(shè)置(Audited Regions)

如果需要每個(gè)屬性或每個(gè)方法都去指定nonnull和nullable,是一件非常繁瑣的事。蘋果為了減輕我們的工作量,專門提供了兩個(gè)宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。在這兩個(gè)宏之間的代碼,所有簡(jiǎn)單指針對(duì)象都被假定為nonnull,因此我們只需要去指定那些nullable的指針。如下代碼所示:

  1. NS_ASSUME_NONNULL_BEGIN
  2. @interface TestNullabilityClass () 
  3.  
  4. @property (nonatomic, copy) NSArray * items; 
  5.  
  6.  
  7. - (id)itemWithName:(nullable NSString *)name; 
  8.  
  9. @end 
  10. NS_ASSUME_NONNULL_END

在上面的代碼中,items屬性默認(rèn)是nonnull的,itemWithName:方法的返回值也是nonnull,而參數(shù)是指定為nullable的。

不過(guò),為了安全起見(jiàn),蘋果還制定了幾條規(guī)則:

  • typedef定義的類型的nullability特性通常依賴于上下文,即使是在Audited Regions中,也不能假定它為nonnull。
  • 復(fù)雜的指針類型(如id *)必須顯示去指定是nonnull還是nullable。例如,指定一個(gè)指向nullable對(duì)象的nonnull指針,可以使用”__nullable id * __nonnull”。
  • 我們經(jīng)常使用的NSError **通常是被假定為一個(gè)指向nullable NSError對(duì)象的nullable指針。

兼容性

因?yàn)镹ullability Annotations是Xcode 6.3新加入的,所以我們需要考慮之前的老代碼。實(shí)際上,蘋果已以幫我們處理好了這種兼容問(wèn)題,我們可以安全地使用它們:

老代碼仍然能正常工作,即使對(duì)nonnull對(duì)象使用了nil也沒(méi)有問(wèn)題。

老代碼在需要和swift混編時(shí),在新的swift編譯器下會(huì)給出一個(gè)警告。

nonnull不會(huì)影響性能。事實(shí)上,我們?nèi)匀豢梢栽谶\(yùn)行時(shí)去判斷我們的對(duì)象是否為nil。

事實(shí)上,我們可以將nonnull/nullable與我們的斷言和異常一起看待,其需要處理的問(wèn)題都是同一個(gè):違反約定是一個(gè)程序員的錯(cuò)誤。特別是,返回值是我們可控的東西,如果返回值是nonnull的,則我們不應(yīng)該返回nil,除非是為了向后兼容。

參考

Nullability and Objective-C

#p#

weak的生命周期

我們都知道weak表示的是一個(gè)弱引用,這個(gè)引用不會(huì)增加對(duì)象的引用計(jì)數(shù),并且在所指向的對(duì)象被釋放之后,weak指針會(huì)被設(shè)置的為nil。weak引用通常是用于處理循環(huán)引用的問(wèn)題,如代理及block的使用中,相對(duì)會(huì)較多的使用到weak。

之前對(duì)weak的實(shí)現(xiàn)略有了解,知道它的一個(gè)基本的生命周期,但具體是怎么實(shí)現(xiàn)的,了解得不是太清晰。今天又翻了翻《Objective-C高級(jí)編程》關(guān)于__weak的講解,在此做個(gè)筆記。

我們以下面這行代碼為例:

代碼清單1:示例代碼

  1. id __weak obj1 = obj; 

當(dāng)我們初始化一個(gè)weak變量時(shí),runtime會(huì)調(diào)用objc_initWeak函數(shù)。這個(gè)函數(shù)在Clang中的聲明如下:

  1. id objc_initWeak(id *object, id value); 

其具體實(shí)現(xiàn)如下:

  1. id objc_initWeak(id *object, id value) 
  2. *object = 0
  3. return objc_storeWeak(object, value); 

示例代碼輪換成編譯器的模擬代碼如下:

  1. id obj1; 
  2. objc_initWeak(&obj1, obj); 

因此,這里所做的事是先將obj1初始化為0(nil),然后將obj1的地址及obj作為參數(shù)傳遞給objc_storeWeak函數(shù)。

objc_initWeak函數(shù)有一個(gè)前提條件:就是object必須是一個(gè)沒(méi)有被注冊(cè)為_(kāi)_weak對(duì)象的有效指針。而value則可以是null,或者指向一個(gè)有效的對(duì)象。

如果value是一個(gè)空指針或者其指向的對(duì)象已經(jīng)被釋放了,則object是zero-initialized的。否則,object將被注冊(cè)為一個(gè)指向value的__weak對(duì)象。而這事應(yīng)該是objc_storeWeak函數(shù)干的。objc_storeWeak的函數(shù)聲明如下:

  1. id objc_storeWeak(id *location, id value); 

其具體實(shí)現(xiàn)如下:

  1. id objc_storeWeak(id *location, id newObj) 
  2. id oldObj; 
  3. SideTable *oldTable; 
  4. SideTable *newTable; 
  5.  
  6. ...... 
  7.  
  8. // Acquire locks for old and new values. 
  9. // Order by lock address to prevent lock ordering problems. 
  10. // Retry if the old value changes underneath us. 
  11. retry: 
  12. oldObj = *location; 
  13.  
  14. oldTable = SideTable::tableForPointer(oldObj); 
  15. newTable = SideTable::tableForPointer(newObj); 
  16.  
  17. ...... 
  18.  
  19. if (*location != oldObj) { 
  20. OSSpinLockUnlock(lock1); 
  21. #if SIDE_TABLE_STRIPE > 1 
  22. if (lock1 != lock2) OSSpinLockUnlock(lock2); 
  23. #endif 
  24. goto retry; 
  25.  
  26. if (oldObj) { 
  27. weak_unregister_no_lock(&oldTable->weak_table, oldObj, location); 
  28. if (newObj) { 
  29. newObj = weak_register_no_lock(&newTable->weak_table, newObj,location); 
  30. // weak_register_no_lock returns NULL if weak store should be rejected 
  31. // Do not set *location anywhere else. That would introduce a race. 
  32. *location = newObj; 
  33.  
  34. ...... 
  35.  
  36. return newObj; 

我們撇開(kāi)源碼中各種鎖操作,來(lái)看看這段代碼都做了些什么。在此之前,我們先來(lái)了解下weak表和SideTable。

weak表是一個(gè)弱引用表,實(shí)現(xiàn)為一個(gè)weak_table_t結(jié)構(gòu)體,存儲(chǔ)了某個(gè)對(duì)象相關(guān)的的所有的弱引用信息。其定義如下(具體定義在objc-weak.h中):

  1. struct weak_table_t { 
  2. weak_entry_t *weak_entries; 
  3. size_t num_entries; 
  4. ...... 
  5. }; 

其中weak_entry_t是存儲(chǔ)在弱引用表中的一個(gè)內(nèi)部結(jié)構(gòu)體,它負(fù)責(zé)維護(hù)和存儲(chǔ)指向一個(gè)對(duì)象的所有弱引用hash表。其定義如下:

  1. struct weak_entry_t { 
  2. DisguisedPtr<objc_object> referent; 
  3. union { 
  4. struct { 
  5. weak_referrer_t *referrers; 
  6. uintptr_t out_of_line : 1
  7. ...... 
  8. }; 
  9. struct { 
  10. // out_of_line=0 is LSB of one of these (don't care which) 
  11. weak_referrer_t inline_referrers[WEAK_INLINE_COUNT]; 
  12. }; 
  13. }; 
  14. }; 

其中referent是被引用的對(duì)象,即示例代碼中的obj對(duì)象。下面的union即存儲(chǔ)了所有指向該對(duì)象的弱引用。由注釋可以看到,當(dāng)out_of_line等于0時(shí),hash表被一個(gè)數(shù)組所代替。另外,所有的弱引用對(duì)象的地址都是存儲(chǔ)在weak_referrer_t指針的地址中。其定義如下:

typedef objc_object ** weak_referrer_t;

SideTable是一個(gè)用C++實(shí)現(xiàn)的類,它的具體定義在NSObject.mm中,我們來(lái)看看它的一些成員變量的定義:

  1. class SideTable { 
  2. private
  3. static uint8_t table_buf[SIDE_TABLE_STRIPE * SIDE_TABLE_SIZE]; 
  4.  
  5. public
  6.  
  7. RefcountMap refcnts; 
  8. weak_table_t weak_table; 
  9.  
  10. ...... 
  11.  

RefcountMap refcnts,大家應(yīng)該能猜到這個(gè)做什么用的吧?看著像是引用計(jì)數(shù)什么的。哈哈,貌似就是啊,這東東存儲(chǔ)了一個(gè)對(duì)象的引用計(jì)數(shù)的信息。當(dāng)然,我們?cè)谶@里不去探究它,我們關(guān)注的是weak_table。這個(gè)成員變量指向的就是一個(gè)對(duì)象的weak表。

了解了weak表和SideTable,讓我們?cè)倩剡^(guò)頭來(lái)看看objc_storeWeak。首先是根據(jù)weak指針找到其指向的老的對(duì)象:

  1. oldObj = *location; 

然后獲取到與新舊對(duì)象相關(guān)的SideTable對(duì)象:

  1. oldTable = SideTable::tableForPointer(oldObj); 
  2. newTable = SideTable::tableForPointer(newObj); 
  3.  
  4. 下面要做的就是在老對(duì)象的weak表中移除指向信息,而在新對(duì)象的weak表中建立關(guān)聯(lián)信息: 
  5.  
  6. if (oldObj) { 
  7. weak_unregister_no_lock(&oldTable->weak_table, oldObj, location); 
  8. if (newObj) { 
  9. newObj = weak_register_no_lock(&newTable->weak_table, newObj,location); 
  10. // weak_register_no_lock returns NULL if weak store should be rejected 

接下來(lái)讓弱引用指針指向新的對(duì)象:

  1. *location = newObj; 

***會(huì)返回這個(gè)新對(duì)象:

  1. return newObj; 

objc_storeWeak的基本實(shí)現(xiàn)就是這樣。當(dāng)然,在objc_initWeak中調(diào)用objc_storeWeak時(shí),老對(duì)象是空的,所有不會(huì)執(zhí)行weak_unregister_no_lock操作。

而當(dāng)weak引用指向的對(duì)象被釋放時(shí),又是如何去處理weak指針的呢?當(dāng)釋放對(duì)象時(shí),其基本流程如下:

調(diào)用objc_release

因?yàn)閷?duì)象的引用計(jì)數(shù)為0,所以執(zhí)行dealloc

在dealloc中,調(diào)用了_objc_rootDealloc函數(shù)

在_objc_rootDealloc中,調(diào)用了object_dispose函數(shù)

調(diào)用objc_destructInstance

***調(diào)用objc_clear_deallocating

我們重點(diǎn)關(guān)注一下***一步,objc_clear_deallocating的具體實(shí)現(xiàn)如下:

  1. void objc_clear_deallocating(id obj) 
  2. ...... 
  3.  
  4. SideTable *table = SideTable::tableForPointer(obj); 
  5.  
  6. // clear any weak table items 
  7. // clear extra retain count and deallocating bit 
  8. // (fixme warn or abort if extra retain count == 0 ?) 
  9. OSSpinLockLock(&table->slock); 
  10. if (seen_weak_refs) { 
  11. arr_clear_deallocating(&table->weak_table, obj); 
  12. ...... 

我們可以看到,在這個(gè)函數(shù)中,首先取出對(duì)象對(duì)應(yīng)的SideTable實(shí)例,如果這個(gè)對(duì)象有關(guān)聯(lián)的弱引用,則調(diào)用arr_clear_deallocating來(lái)清除對(duì)象的弱引用信息。我們來(lái)看看arr_clear_deallocating具體實(shí)現(xiàn):

  1. PRIVATE_EXTERN void arr_clear_deallocating(weak_table_t *weak_table, id referent) { 
  2. weak_entry_t *entry = weak_entry_for_referent(weak_table, referent); 
  3. if (entry == NULL) { 
  4. ...... 
  5. return
  6. // zero out references 
  7. for (int i = 0; i < entry->referrers.num_allocated; ++i) { 
  8. id *referrer = entry->referrers.refs[i].referrer; 
  9. if (referrer) { 
  10. if (*referrer == referent) { 
  11. *referrer = nil; 
  12. else if (*referrer) { 
  13. _objc_inform("__weak variable @ %p holds %p instead of %p\n", referrer, *referrer, referent); 
  14.  
  15. weak_entry_remove_no_lock(weak_table, entry); 
  16. weak_table->num_weak_refs--; 

這個(gè)函數(shù)首先是找出對(duì)象對(duì)應(yīng)的weak_entry_t鏈表,然后挨個(gè)將弱引用置為nil。***清理對(duì)象的記錄。

通過(guò)上面的描述,我們基本能了解一個(gè)weak引用從生到死的過(guò)程。從這個(gè)流程可以看出,一個(gè)weak引用的處理涉及各種查表、添加與刪除操作,還是有一定消耗的。所以如果大量使用__weak變量的話,會(huì)對(duì)性能造成一定的影響。那么,我們應(yīng)該在什么時(shí)候去使用weak呢?《Objective-C高級(jí)編程》給我們的建議是只在避免循環(huán)引用的時(shí)候使用__weak修飾符。

另外,在clang中,還提供了不少關(guān)于weak引用的處理函數(shù)。如objc_loadWeak, objc_destroyWeak, objc_moveWeak等,我們可以在蘋果的開(kāi)源代碼中找到相關(guān)的實(shí)現(xiàn)。等有時(shí)間,我再好好研究研究。

參考

《Objective-C高級(jí)編程》1.4: __weak修飾符

Clang 3.7 documentation – Objective-C Automatic Reference Counting (ARC)

apple opensource – NSObject.mm

#p#

零碎

CAGradientLayer

CAGradientLayer類是用于在其背景色上繪制一個(gè)顏色漸變,以填充層的整個(gè)形狀,包括圓角。這個(gè)類繼承自CALayer類,使用起來(lái)還是很方便的。

與Quartz 2D中的漸變處理類似,一個(gè)漸變有一個(gè)起始位置(startPoint)和一個(gè)結(jié)束位置(endPoint),在這兩個(gè)位置之間,我們可以指定一組顏色值(colors,元素是CGColorRef對(duì)象),可以是兩個(gè),也可以是多個(gè),每個(gè)顏色值會(huì)對(duì)應(yīng)一個(gè)位置(locations)。另外,漸變還分為軸向漸變和徑向漸變。

我們寫個(gè)實(shí)例來(lái)看看CAGradientLayer的具體使用:

  1. CAGradientLayer *layer = [CAGradientLayer layer]; 
  2. layer.startPoint = (CGPoint){0.5f, 0.0f}; 
  3. layer.endPoint = (CGPoint){0.5f, 1.0f}; 
  4. layer.colors = [NSArray arrayWithObjects:(id)[UIColor blueColor].CGColor, (id)[UIColor redColor].CGColor, (id)[UIColor greenColor].CGColor, nil]; 
  5. layer.locations = @[@0.0f, @0.6f, @1.0f]; 
  6. layer.frame = self.view.layer.bounds; 
  7.  
  8. [self.view.layer insertSublayer:layer atIndex:0]; 

參考

CAGradientLayer Class Reference

Xcode中Ineligible Devices的處理

換了臺(tái)新電腦,裝了個(gè)Xcode 6.3,整了個(gè)新證書和profile,然后打開(kāi)Xcode,連上手機(jī)。額,然后發(fā)現(xiàn)設(shè)備居然被標(biāo)識(shí)為Ineligible Devices,沒(méi)認(rèn)出來(lái)。情況類似于下圖:

電腦是受信任的,證書和profile也都是OK的。試了幾次重啟Xcode和重新連接手機(jī),無(wú)效。設(shè)備就是選不了。***是在Product->Destination里面才選中這個(gè)設(shè)備的。不過(guò)在工具欄還是不能選擇,郁悶,求解。

iOS 7后隱藏UITextField的光標(biāo)

新項(xiàng)目只支持iOS 7后,很多事情變得簡(jiǎn)單多了,就像隱藏UITextField的光標(biāo)一樣,就簡(jiǎn)單的一句話:

textFiled.tintColor = [UIColor clearColor];

通常我們用UIPickerView作為我們的UITextField的inputView時(shí),我們是需要隱藏光標(biāo)的。當(dāng)然,如果想換個(gè)光標(biāo)顏色,也是這么處理。

這么處理的有個(gè)遺留問(wèn)題是:通常我們使用UIPickerView作為UITextField的inputView時(shí), 并不希望去執(zhí)行各種菜單操作(全選、復(fù)制、粘帖),但只是去設(shè)置UITextField的tintColor時(shí),我們?nèi)匀豢梢詧?zhí)行這邊操作,所以需要加額外的處理。這個(gè)問(wèn)題,我們可以這樣處理:在textFieldShouldBeginEditing:中,我們把UITextField的userInteractionEnabled設(shè)置為NO,然后在textFieldShouldEndEditing:,將將這個(gè)值設(shè)置回來(lái)。如下:

  1. - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 
  2.  
  3. textField.userInteractionEnabled = NO; 
  4.  
  5. return YES; 
  6.  
  7. - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { 
  8.  
  9. textField.userInteractionEnabled = YES; 
  10.  
  11. return YES; 

這樣就OK了。當(dāng)然這只是我們當(dāng)前使用的一種處理方式,還有其它的方法,直接google或者stackoverflow吧。

iOS 7后UIAlertView中文字左對(duì)齊問(wèn)題

在iOS 7之前,如果我們想要讓UIAlertView中的文字居左顯示的話,可以使用以下這段代碼來(lái)處理:

  1. for (UIView *view in alert.subviews) { 
  2. if([[view class] isSubclassOfClass:[UILabel class]]) { 
  3. ((UILabel*)view).textAlignment = NSTextAlignmentLeft; 

但很遺憾的是,在iOS 7之后,蘋果不讓我們這么干了。我們?nèi)トIAlertView的subviews時(shí),獲得的只是一個(gè)空數(shù)組,我們沒(méi)有辦法獲取到我們想要的label。怎么辦?三條路:告訴產(chǎn)品經(jīng)理和UED說(shuō)這個(gè)實(shí)現(xiàn)不了(當(dāng)然,這個(gè)是會(huì)被鄙視的,人家會(huì)說(shuō)你能力差);自己寫;找第三方開(kāi)源代碼。嘿嘿,不過(guò)由于最近時(shí)間緊,所以我決定跟他們說(shuō)實(shí)現(xiàn)不了,哈哈。不過(guò)在github上找了一個(gè)開(kāi)源的,Custom iOS AlertView,star的數(shù)量也不少,看來(lái)不錯(cuò),回頭好好研究研究。

責(zé)任編輯:chenqingxiang 來(lái)源: 南峰子的技術(shù)博客
相關(guān)推薦

2015-07-06 10:09:33

iosFoundationNSHashTable

2015-07-07 14:05:22

iOS技巧

2019-07-23 09:00:00

vuejavascript前端

2015-10-21 13:42:54

iOS開(kāi)發(fā)watch OS2

2014-07-23 10:08:34

Angular前端項(xiàng)目

2024-01-09 18:01:38

2015-06-10 10:56:50

iOS開(kāi)發(fā)技巧

2024-08-13 08:00:00

2021-10-27 08:00:00

DevSecOps開(kāi)發(fā)安全

2015-07-28 20:34:01

Android開(kāi)發(fā)框架

2016-10-25 14:27:16

開(kāi)源Ruby on RaiWeb框架

2016-12-01 08:36:18

編程云環(huán)境云戰(zhàn)略

2015-10-14 10:54:20

iOS開(kāi)發(fā)讀書

2020-03-05 12:12:54

數(shù)據(jù)Python開(kāi)發(fā)

2025-03-24 15:00:13

鴻蒙HarmonyOS

2021-01-05 05:15:02

Github 前端倉(cāng)庫(kù)

2015-04-01 10:55:55

2022-04-15 09:01:18

前端工具UTF8編碼

2018-10-23 10:35:20

react.jsReact面試題前端

2021-04-21 07:51:06

Vue 開(kāi)發(fā)VS CodeVetur
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)