精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

大牛說:這是不可錯過的iOS開發技巧(二)

移動開發 iOS
通常要想創建一個特殊效果(如blur效果),可以創建一個UIVisualEffectView視圖對象,這個對象提供了一種簡單的方式來實現復雜的視覺效果。

換了個廠子,還不到1個月。哎,著實是累啊,基本上是996.5的節奏,只會更多。加班把我快加吐了,但人在江湖,身不由已啊。為了討口飯吃,命也不要了。誰讓咱只是個臭寫代碼的呢。不過加班是多,只是長得太丑,所有沒辦法,沒時間也得抽時間來學習。不然,飯都沒得吃了,還得養家糊口呢。

本期總結的內容不是很多,主要有以下幾個問題:

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

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

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

通常要想創建一個特殊效果(如blur效果),可以創建一個UIVisualEffectView視圖對象,這個對象提供了一種簡單的方式來實現復雜的視覺效果。這個可以把這個對象看作是效果的一個容器,實際的效果會影響到該視圖對象底下的內容,或者是添加到該視圖對象的contentView中的內容。

我們舉個例子來看看如果使用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) 

這段代碼是在當前視圖控制器上添加了一個UIImageView作為背景圖。

我們可以看到UIVisualEffectView還是非常簡單的。需要注意是的,不應該直接添加子視圖到UIVisualEffectView視圖中,而是應該添加到UIVisualEffectView對象的contentView中。

另外,盡量避免將UIVisualEffectView對象的alpha值設置為小于1.0的值,因為創建半透明的視圖會導致系統在離屏渲染時去對UIVisualEffectView對象及所有的相關的子視圖做混合操作。這不但消耗CPU/GPU,也可能會導致許多效果顯示不正確或者根本不顯示。

我們在上面看到,初始化一個UIVisualEffectView對象的方法是UIVisualEffectView(effect: blurEffect),其定義如下:

  1. init(effect effect: UIVisualEffect) 

這個方法的參數是一個UIVisualEffect對象。我們查看官方文檔,可以看到在UIKit中,定義了幾個專門用來創建視覺特效的,它們分別是UIVisualEffect、UIBlurEffect和UIVibrancyEffect。它們的繼承層次如下所示:

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

UIVisualEffect是一個繼承自NSObject的創建視覺效果的基類,然而這個類除了繼承自NSObject的屬性和方法外,沒有提供任何新的屬性和方法。其主要目的是用于初始化UIVisualEffectView,在這個初始化方法中可以傳入UIBlurEffect或者UIVibrancyEffect對象。

一個UIBlurEffect對象用于將blur(毛玻璃)效果應用于UIVisualEffectView視圖下面的內容。如上面的示例所示。不過,這個對象的效果并不影響UIVisualEffectView對象的contentView中的內容。

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

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

其主要是根據色調(hue)來確定特效視圖與底部視圖的混合。

與UIBlurEffect不同的是,UIVibrancyEffect主要用于放大和調整UIVisualEffectView視圖下面的內容的顏色,同時讓UIVisualEffectView的contentView中的內容看起來更加生動。通常UIVibrancyEffect對象是與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的子視圖都必須實現tintColorDidChange方法并更新自己。需要注意的是,我們使用UIVibrancyEffect(forBlurEffect:)方法創建UIVibrancyEffect時,參數blurEffect必須是我們想加效果的那個blurEffect,否則可能不是我們想要的效果。

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

class func notificationCenterVibrancyEffect() -> UIVibrancyEffect!

這個方法創建一個用于通知中心的Today擴展的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)問題的處理 — Nullability Annotations

最近在用Xcode 6.3寫代碼,一些涉及到對象的代碼會報如下編譯器警告:

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

于是google了一下,發現這是Xcode 6.3的一個新特性,即nullability annotations。

#p#

Nullability Annotations

我們都知道在swift中,可以使用!和?來表示一個對象是optional的還是non-optional,如view?和view!。而在Objective-C中則沒有這一區分,view即可表示這個對象是optional,也可表示是non-optioanl。這樣就會造成一個問題:在Swift與Objective-C混編時,Swift編譯器并不知道一個Objective-C對象到底是optional還是non-optional,因此這種情況下編譯器會隱式地將Objective-C的對象當成是non-optional。

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

我們來看看以下的實例,

  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 

不過這只是一個警告,程序還是能編譯通過并運行。

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

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

在屬性聲明中,也增加了兩個相應的特性,因此上例中的items屬性可以如下聲明:

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

當然也可以用以下這種方式:

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

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

Nonnull區域設置(Audited Regions)

如果需要每個屬性或每個方法都去指定nonnull和nullable,是一件非常繁瑣的事。蘋果為了減輕我們的工作量,專門提供了兩個宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。在這兩個宏之間的代碼,所有簡單指針對象都被假定為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屬性默認是nonnull的,itemWithName:方法的返回值也是nonnull,而參數是指定為nullable的。

不過,為了安全起見,蘋果還制定了幾條規則:

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

兼容性

因為Nullability Annotations是Xcode 6.3新加入的,所以我們需要考慮之前的老代碼。實際上,蘋果已以幫我們處理好了這種兼容問題,我們可以安全地使用它們:

老代碼仍然能正常工作,即使對nonnull對象使用了nil也沒有問題。

老代碼在需要和swift混編時,在新的swift編譯器下會給出一個警告。

nonnull不會影響性能。事實上,我們仍然可以在運行時去判斷我們的對象是否為nil。

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

參考

Nullability and Objective-C

#p#

weak的生命周期

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

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

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

代碼清單1:示例代碼

  1. id __weak obj1 = obj; 

當我們初始化一個weak變量時,runtime會調用objc_initWeak函數。這個函數在Clang中的聲明如下:

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

其具體實現如下:

  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作為參數傳遞給objc_storeWeak函數。

objc_initWeak函數有一個前提條件:就是object必須是一個沒有被注冊為__weak對象的有效指針。而value則可以是null,或者指向一個有效的對象。

如果value是一個空指針或者其指向的對象已經被釋放了,則object是zero-initialized的。否則,object將被注冊為一個指向value的__weak對象。而這事應該是objc_storeWeak函數干的。objc_storeWeak的函數聲明如下:

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

其具體實現如下:

  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; 

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

weak表是一個弱引用表,實現為一個weak_table_t結構體,存儲了某個對象相關的的所有的弱引用信息。其定義如下(具體定義在objc-weak.h中):

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

其中weak_entry_t是存儲在弱引用表中的一個內部結構體,它負責維護和存儲指向一個對象的所有弱引用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是被引用的對象,即示例代碼中的obj對象。下面的union即存儲了所有指向該對象的弱引用。由注釋可以看到,當out_of_line等于0時,hash表被一個數組所代替。另外,所有的弱引用對象的地址都是存儲在weak_referrer_t指針的地址中。其定義如下:

typedef objc_object ** weak_referrer_t;

SideTable是一個用C++實現的類,它的具體定義在NSObject.mm中,我們來看看它的一些成員變量的定義:

  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,大家應該能猜到這個做什么用的吧?看著像是引用計數什么的。哈哈,貌似就是啊,這東東存儲了一個對象的引用計數的信息。當然,我們在這里不去探究它,我們關注的是weak_table。這個成員變量指向的就是一個對象的weak表。

了解了weak表和SideTable,讓我們再回過頭來看看objc_storeWeak。首先是根據weak指針找到其指向的老的對象:

  1. oldObj = *location; 

然后獲取到與新舊對象相關的SideTable對象:

  1. oldTable = SideTable::tableForPointer(oldObj); 
  2. newTable = SideTable::tableForPointer(newObj); 
  3.  
  4. 下面要做的就是在老對象的weak表中移除指向信息,而在新對象的weak表中建立關聯信息: 
  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 

接下來讓弱引用指針指向新的對象:

  1. *location = newObj; 

***會返回這個新對象:

  1. return newObj; 

objc_storeWeak的基本實現就是這樣。當然,在objc_initWeak中調用objc_storeWeak時,老對象是空的,所有不會執行weak_unregister_no_lock操作。

而當weak引用指向的對象被釋放時,又是如何去處理weak指針的呢?當釋放對象時,其基本流程如下:

調用objc_release

因為對象的引用計數為0,所以執行dealloc

在dealloc中,調用了_objc_rootDealloc函數

在_objc_rootDealloc中,調用了object_dispose函數

調用objc_destructInstance

***調用objc_clear_deallocating

我們重點關注一下***一步,objc_clear_deallocating的具體實現如下:

  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. ...... 

我們可以看到,在這個函數中,首先取出對象對應的SideTable實例,如果這個對象有關聯的弱引用,則調用arr_clear_deallocating來清除對象的弱引用信息。我們來看看arr_clear_deallocating具體實現:

  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--; 

這個函數首先是找出對象對應的weak_entry_t鏈表,然后挨個將弱引用置為nil。***清理對象的記錄。

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

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

參考

《Objective-C高級編程》1.4: __weak修飾符

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

apple opensource – NSObject.mm

#p#

零碎

CAGradientLayer

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

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

我們寫個實例來看看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的處理

換了臺新電腦,裝了個Xcode 6.3,整了個新證書和profile,然后打開Xcode,連上手機。額,然后發現設備居然被標識為Ineligible Devices,沒認出來。情況類似于下圖:

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

iOS 7后隱藏UITextField的光標

新項目只支持iOS 7后,很多事情變得簡單多了,就像隱藏UITextField的光標一樣,就簡單的一句話:

textFiled.tintColor = [UIColor clearColor];

通常我們用UIPickerView作為我們的UITextField的inputView時,我們是需要隱藏光標的。當然,如果想換個光標顏色,也是這么處理。

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

  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了。當然這只是我們當前使用的一種處理方式,還有其它的方法,直接google或者stackoverflow吧。

iOS 7后UIAlertView中文字左對齊問題

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

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

但很遺憾的是,在iOS 7之后,蘋果不讓我們這么干了。我們去取UIAlertView的subviews時,獲得的只是一個空數組,我們沒有辦法獲取到我們想要的label。怎么辦?三條路:告訴產品經理和UED說這個實現不了(當然,這個是會被鄙視的,人家會說你能力差);自己寫;找第三方開源代碼。嘿嘿,不過由于最近時間緊,所以我決定跟他們說實現不了,哈哈。不過在github上找了一個開源的,Custom iOS AlertView,star的數量也不少,看來不錯,回頭好好研究研究。

責任編輯:chenqingxiang 來源: 南峰子的技術博客
相關推薦

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開發watch OS2

2014-07-23 10:08:34

Angular前端項目

2015-06-10 10:56:50

iOS開發技巧

2024-08-13 08:00:00

2024-01-09 18:01:38

2021-10-27 08:00:00

DevSecOps開發安全

2015-07-28 20:34:01

Android開發框架

2016-10-25 14:27:16

開源Ruby on RaiWeb框架

2016-12-01 08:36:18

編程云環境云戰略

2015-10-14 10:54:20

iOS開發讀書

2020-03-05 12:12:54

數據Python開發

2025-03-24 15:00:13

鴻蒙HarmonyOS

2015-04-01 10:55:55

2022-04-15 09:01:18

前端工具UTF8編碼

2021-01-05 05:15:02

Github 前端倉庫

2018-10-23 10:35:20

react.jsReact面試題前端

2021-04-21 07:51:06

Vue 開發VS CodeVetur
點贊
收藏

51CTO技術棧公眾號

欧美高清视频在线观看| 红桃av永久久久| 成人乱色短篇合集| 国产无遮挡裸体免费视频| 98视频精品全部国产| 日韩欧美一区视频| 青少年xxxxx性开放hg| 日韩一级片免费观看| 日韩vs国产vs欧美| 欧美激情亚洲激情| 日韩不卡av在线| aiai久久| 在线成人小视频| 337p粉嫩大胆噜噜噜鲁| 日本电影全部在线观看网站视频| 高清国产一区二区| 国产精品久久久久av| 久久精品国产av一区二区三区| 国内黄色精品| 亚洲精品av在线播放| 97超碰人人爽| 欧美动物xxx| 亚洲一区二区三区美女| 亚洲欧美影院| 美女做暖暖视频免费在线观看全部网址91 | 久久久成人精品一区二区三区| 日本高清视频免费看| 捆绑紧缚一区二区三区视频| 欧美一乱一性一交一视频| 91麻豆精品成人一区二区| 国产精品亚洲人成在99www| 69堂精品视频| 亚洲国产日韩欧美在线观看| 三级在线观看视频| 亚洲国产一区二区视频| 影音先锋亚洲视频| porn视频在线观看| 99久久久国产精品| 国产精品一区二区不卡视频| 国产婷婷在线视频| 久久91精品国产91久久小草| 国产成人拍精品视频午夜网站| 国产在线观看免费av| 欧美成人69av| 欧美成人精品一区二区| 国产第一页精品| 欧美熟乱15p| 亚洲欧美一区二区三区四区| 在线免费播放av| 精品国产导航| 337p日本欧洲亚洲大胆精品| 亚洲成年人av| 日本高清精品| 日韩精品一区二区三区蜜臀 | 国产美女永久无遮挡| 国产区在线观看| 136国产福利精品导航| 亚洲欧美日韩精品久久久| av在线播放网| 国产精品久久久久精k8 | 日韩午夜电影| 欧美性视频在线| 五月天激情国产综合婷婷婷| 亚洲伊人观看| 国产精品69av| 亚洲最新av网站| 精品一区二区在线观看| 91中文字幕一区| 亚洲国产精品视频在线| 成人免费视频视频在线观看免费 | 成人区精品一区二区婷婷| 伊人久久五月天| 性少妇xx生活| 中文字幕免费一区二区| 久久久久久久999| 国产污污视频在线观看| 天堂影院一区二区| 国产欧美一区二区白浆黑人| 一二三区中文字幕| 国产精品夜夜嗨| 国产精品永久入口久久久| 亚洲av成人无码网天堂| 国产欧美精品一区| 欧美性受xxxx黑人猛交88| 97天天综合网| 在线日韩一区二区| 一级日本黄色片| 欧美韩一区二区| 中文字幕亚洲综合久久筱田步美| 丝袜 亚洲 另类 欧美 重口 | 亚洲欧洲制服丝袜| 成人午夜精品久久久久久久蜜臀| 亚洲欧美电影| 欧美丰满嫩嫩电影| 国产激情第一页| 日韩精品午夜| 午夜精品久久久久久99热| 国产免费www| 成人中文字幕电影| 日韩精品久久久免费观看| av黄色在线| 日韩欧美aaa| 成人三级做爰av| 国产精品一线天粉嫩av| 欧美激情一区二区三区久久久| 久久精品视频5| 国产成人一区在线| 日韩视频在线播放| 美女日批视频在线观看| 欧美色偷偷大香| 国产原创剧情av| 国产国产精品| 26uuu久久噜噜噜噜| 国产三级视频在线播放| 久久精品视频一区二区| 97在线国产视频| 国产在线一区不卡| 一区二区三区国产视频| 亚洲天堂日韩av| 国产成人免费视频网站| 亚洲日本无吗高清不卡| 中文字幕在线免费观看视频| 精品国产凹凸成av人网站| 午夜激情视频在线播放| 欧美亚洲免费| 国产区一区二区| 在线免费观看的av| 欧美二区在线观看| av片在线免费看| 久久久夜精品| 久久久一本精品99久久精品| 欧美寡妇性猛交xxx免费| 欧美二区在线观看| 成人欧美一区二区三区黑人一| 性感少妇一区| 精品在线不卡| 免费在线小视频| 337p日本欧洲亚洲大胆精品| 草视频在线观看| 国产一区激情在线| 艳母动漫在线观看| 日韩三级成人| xvideos亚洲人网站| 这里只有精品免费视频| 久久久久久久久久久久久久久99 | 欧美日韩精品在线一区二区| 亚洲综合影院| 久久久久久久久久久亚洲| 精品国产无码一区二区| 尤物在线观看一区| 性生交大片免费看l| 一区二区三区四区日韩| 亚洲一区二区三区成人在线视频精品| 日本免费中文字幕在线| 欧美女孩性生活视频| 久草福利资源在线| 国产在线日韩欧美| 国产91视频一区| 99re6热只有精品免费观看| 欧美情侣性视频| 黄色av免费观看| 亚洲www啪成人一区二区麻豆| 国产女主播在线播放| 伊人久久综合| 精品国产乱码久久久久久丨区2区| 黄页网站在线观看免费| 亚洲电影在线观看| av图片在线观看| 欧美激情在线免费观看| 日韩av卡一卡二| 午夜精彩国产免费不卡不顿大片| 成人看片在线| 在线天堂资源| www国产精品视频| 精品国产伦一区二区三区| 午夜精品久久久久久久99水蜜桃| b站大片免费直播| 精品午夜一区二区三区在线观看| av在线免费观看国产| 久久久伦理片| 国产精品视频一| 性xxxxfjsxxxxx欧美| 日韩av网站导航| 中文字幕日韩国产| 亚洲一区二区视频在线| 免费在线观看成年人视频| 另类综合日韩欧美亚洲| 青青草国产免费| 欧美人与牛zoz0性行为| 成人淫片在线看| 蜜桃视频在线观看免费视频| 色偷偷噜噜噜亚洲男人的天堂| 国产成人av免费看| 色婷婷久久一区二区三区麻豆| 国产一区在线观看免费| av日韩在线网站| 欧美日韩精品区别| 亚洲男人影院| 九九久久九九久久| 久久99久久人婷婷精品综合| 91免费版黄色| 精品成人免费一区二区在线播放| 久久99精品久久久久久青青91| 九一国产在线| 亚洲的天堂在线中文字幕| 中文字幕一区二区久久人妻| 婷婷丁香激情综合| 侵犯稚嫩小箩莉h文系列小说| 91免费国产在线观看| 日本亚洲一区二区三区| 日本欧美一区二区| 国产极品在线视频| 欧美激情综合| 午夜精品电影在线观看| 噜噜噜狠狠夜夜躁精品仙踪林| 成人精品久久久| 欧洲av一区二区| 8x拔播拔播x8国产精品 | 日韩免费观看视频| 国产探花在线观看| 免费不卡欧美自拍视频| 成人精品一区二区| 亚洲美女av网站| 日批视频免费播放| 欧美一区2区视频在线观看| 一区二区视频免费观看| 日韩欧美aⅴ综合网站发布| 国产小视频在线看| 亚洲精品视频观看| 色老板免费视频| 中文字幕一区二| 九九热久久免费视频| 国产日韩在线不卡| 少妇久久久久久久久久| 97久久超碰国产精品电影| 高清中文字幕mv的电影| 国产精品白丝av| 久久无码人妻一区二区三区| 捆绑紧缚一区二区三区视频| 无限资源日本好片| 日韩成人伦理电影在线观看| 北条麻妃av高潮尖叫在线观看| 亚洲欧美成人综合| 免费在线观看毛片网站| 久久一区二区三区四区五区 | 高清不卡一区| 亚洲最大的成人网| 久久久久毛片免费观看| 亚洲wwwav| 亚洲精品一区在线| 成人欧美一区二区三区黑人免费| 亚洲精品不卡在线观看| 91视频免费进入| 一区二区中文字幕在线观看| 成人18视频| 久久婷婷国产| 欧美一级二级三级| 欧美中文一区二区| 一本一道久久久a久久久精品91| 99久久亚洲精品蜜臀| 玖玖精品在线视频| 精品动漫一区| 日韩激情免费视频| 日韩1区2区日韩1区2区| 极品粉嫩美女露脸啪啪| 国产成人免费xxxxxxxx| 中文字幕av观看| 国产精品国产三级国产aⅴ入口| 二区三区四区视频| 亚洲在线视频一区| 成人免费视频毛片| 精品视频在线免费看| 国产精品-色哟哟| 亚洲国产精品va在线观看黑人| 欧美少妇另类| 日韩亚洲综合在线| 免费毛片在线看片免费丝瓜视频 | 日韩黄色av| 久久久久久久久久久久久久久久av | 亚洲小视频在线| 国产在线观看a| 69av成年福利视频| 久久国产三级| 国产精品一区二区三区观看| 欧美美乳视频| 亚洲五码在线观看视频| 亚洲一区视频| 日韩av加勒比| 久久夜色精品国产欧美乱极品| 美国精品一区二区| 大伊人狠狠躁夜夜躁av一区| 伊人免费在线观看| 亚洲国产精品电影| 免费av网站在线看| 日韩美女免费线视频| 免费欧美网站| 日韩亚洲欧美精品| 国产一区二区精品| 手机精品视频在线| 久久久精品日韩欧美| 久久视频免费看| 欧美日韩一区高清| 三级在线电影| 久久99久国产精品黄毛片入口| 欧洲av一区二区| 久久99精品国产99久久| 在线一区电影| 日韩一区二区三区不卡视频| thepron国产精品| 国产高潮国产高潮久久久91| 在线免费观看视频一区| 天天爽夜夜爽夜夜爽| 久久视频国产精品免费视频在线| 黑人巨大亚洲一区二区久| 国产嫩草一区二区三区在线观看| 51精产品一区一区三区| 欧美一级裸体视频| 99re成人在线| 国产特黄大片aaaa毛片| 日韩欧美精品三级| av毛片在线| 91久久精品国产| 99成人在线视频| 杨幂毛片午夜性生毛片| 久久精品在线免费观看| 国产成人在线观看网站| 欧美不卡123| 羞羞的视频在线看| 91福利入口| 综合久久综合| 色男人天堂av| 亚洲精品高清在线观看| 国产一区二区三区四区视频| 中文字幕av一区二区三区谷原希美| 中文字幕 在线观看| 免费成人看片网址| 亚洲制服少妇| 18禁裸乳无遮挡啪啪无码免费| 亚洲成人av一区| 天堂v在线观看| 午夜欧美大片免费观看| 噜噜噜狠狠夜夜躁精品仙踪林| 国产 日韩 亚洲 欧美| 成人一级片在线观看| 国产精品suv一区二区| 精品国产一区二区在线观看| 暖暖在线中文免费日本| 国产精品午夜av在线| 伊人精品成人久久综合软件| 毛茸茸free性熟hd| 黄色成人av在线| 国产在线视频福利| 国产乱人伦真实精品视频| 久久人人88| 亚欧精品在线视频| 亚洲综合清纯丝袜自拍| 视频污在线观看| 日韩av电影在线免费播放| 免费成人av| 亚洲美女性囗交| 一区二区三区四区中文字幕| 午夜久久久久久久久久| 欧美激情视频一区二区三区不卡| 丁香婷婷成人| 精品视频一区二区在线| 国产精品区一区二区三区| 国产伦子伦对白视频| 欧美精品福利视频| 亚洲裸色大胆大尺寸艺术写真| www.超碰com| **性色生活片久久毛片| 免费观看a视频| 国产成人精品网站| 久久久久国产| jlzzjizz在线播放观看| 欧美亚日韩国产aⅴ精品中极品| 成人片在线看| 久久本道综合色狠狠五月| 日韩高清不卡在线| 紧身裙女教师波多野结衣| 欧美变态口味重另类| 香蕉久久免费电影| 黄色网zhan| 久久久高清一区二区三区| 国产精品欧美久久久久天天影视| 久久久久久久久久久亚洲| 青青草国产免费一区二区下载| 中文字幕第三区| 91高清视频免费看| 国内在线视频| 亚洲成色最大综合在线| 成人美女视频在线看| 瑟瑟视频在线免费观看| 久久久爽爽爽美女图片| 久久婷婷蜜乳一本欲蜜臀| 女同性恋一区二区三区| 在线播放日韩导航| 另类专区亚洲| 真人抽搐一进一出视频| 一区免费观看视频|