最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

升級(jí)到Swift 4.0可能遇到的坑總結(jié)

 更新時(shí)間:2017年11月15日 10:28:08   作者:ShmilyCoder  
這篇文章主要給大家介紹了關(guān)于升級(jí)到Swift 4.0可能遇到的坑的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用swift4具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

前言

swift4.0已經(jīng)出來(lái)一段時(shí)間,之前已經(jīng)給大家總結(jié)介紹了關(guān)于swift4的新特性,那么本文就來(lái)介紹下當(dāng)swift升級(jí)到swift4在使用中會(huì)遇到哪些問(wèn)題呢?下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

升級(jí)Swift4.0

  • 并不是所有庫(kù)都能做到及時(shí)支持Swift4.0,更何況是在現(xiàn)在連Xcode9也還是beta的狀態(tài)
  • 所以我們僅能做到將自己的業(yè)務(wù)代碼(主工程代碼)部分升級(jí)到Swift4.0,然后同時(shí)保留各種pod庫(kù)在Swift3.2版本。
  • 沒(méi)辦法,誰(shuí)叫Swift4.0也還無(wú)法做到API兼容呢(但愿能在Swift5之前實(shí)現(xiàn)吧)。
  • 至于我說(shuō)的同時(shí)使用兩個(gè)版本的Swift,這是沒(méi)問(wèn)題的,Xcode9支持在項(xiàng)目中同時(shí)使用Swift3.2和Swift4.0。

一. 修改Swift版本

1. 如下圖指定主工程的Swift版本為4.0

2. 修改pod庫(kù)

在Podfile文件的最下方加入如下代碼,指定pod庫(kù)的Swift版本為3.2(這樣會(huì)使得所有的第三方pod庫(kù)的Swift版本都為3.2)

post_install do |installer|
 installer.pods_project.targets.each do |target|
 target.build_configurations.each do |config|
  config.build_settings['SWIFT_VERSION'] = '3.2'
 end 
 end
end

二. 主工程中的代碼修改

1. 列舉一下Swift3.2到Swift4.0的改變(只是我項(xiàng)目中遇到的):

1). Swift4.0中對(duì)于擴(kuò)展的屬性(包括實(shí)例屬性、static屬性、class屬性),都只能使用get方法,不可使用set方法

2). Swift4.0中不再允許復(fù)寫(xiě)擴(kuò)展中的方法(包括實(shí)例方法、static方法、class方法)

      比如:自定義的協(xié)議方法在extension中實(shí)現(xiàn),若某個(gè)類(lèi)遵循了該協(xié)議,其子類(lèi)便不能重寫(xiě)該協(xié)議方法

      解決的方法是: 在每個(gè)需要該協(xié)議的類(lèi)里面都重新遵循該協(xié)議,實(shí)現(xiàn)協(xié)議方法

      個(gè)人想到的辦法,不知道有沒(méi)有其他解決辦法可以提供一下

3). swift3使用#selector指定的方法,只有當(dāng)方法權(quán)限為private時(shí)需要加@objc修飾符,現(xiàn)在Swift4.0全都要加@objc修飾符

4). 自定義的protocol協(xié)議中,有optional修飾的非必須實(shí)現(xiàn)的方法,需要用@objc修飾

5). 字體方面的一些重命名

NSFontAttributeName --- .font 
//或者NSAttributedStringKey.font

NSForegroundColorAttributeName --- .foregroundColor
//NSAttributedStringKey.foregroundColor

NSStrikethroughStyleAttributeName --- .strikethroughStyle
//NSAttributedStringKey.strikethroughStyle

//字符串類(lèi)型的,添加rawValue
NSAttributedStringKey.font.rawValue

//等等等等..........

//大部分類(lèi)似以下,涉及富文本的方法均已改為了NSAttributedStringKey類(lèi)型
addAttributes(_ attrs: [NSAttributedStringKey : Any] = [:], range: NSRange)

三. 項(xiàng)目中遇到的一些的報(bào)錯(cuò)問(wèn)題

3-1. "Closure cannot implicitly capture a mutating self parameter"錯(cuò)誤

在struct中,如果我們?cè)陂]包中使用self,就會(huì)得到Closure cannot implicitly capture a mutating self parameter的錯(cuò)誤提示。比如:

struct RecordModel {
 /// 定義一個(gè)閉包
 var action: (() -> ())?
 var height = 10
 
 self.action = { 
  self.height = 20 
  //Closure cannot implicitly capture a mutating self parameter報(bào)錯(cuò)
 }
}

++并且由于RecordModel的類(lèi)型是struct,我們也沒(méi)發(fā)在action閉包里添加截獲列表。那么是不是就必須使用class了?答案是否定的。有兩種方式可以解決這個(gè)問(wèn)題。++

方案一:為closure增加一個(gè)inout類(lèi)型的參數(shù)

struct RecordModel {
 /// 定義一個(gè)閉包
 var action: ((_ inSelf: inout RecordModel) -> ())?
 var height = 10
 
 self.action = { (inSelf) in
  inSelf.height = 20 
 }
}

根據(jù)inout類(lèi)型的說(shuō)明,我們知道,實(shí)際上這相當(dāng)于增加了一個(gè)隱藏的臨時(shí)變量,self被復(fù)制,然后在closure(閉包)中使用,完成后,再?gòu)?fù)制回self。也就是說(shuō),這個(gè)方法有額外的內(nèi)存開(kāi)銷(xiāo)。如果是struct較大的情形,這么做并不劃算。

方案二:使用UnsafeMutablePointer<Pointee>

==這次采用直接指針的方式對(duì)于struct來(lái)進(jìn)行操作,采用指針的好處是self不會(huì)被多次復(fù)制,性能較高。缺點(diǎn)是你需要自行確定你的代碼的安全。==

struct RecordModel {
 /// 定義一個(gè)閉包
 var action: (() -> ())?
 var height = 10
 
 let selfPointer = UnsafeMutablePointer(&self)
 self.action = { 
  selfPointer.pointee.height = 20 
  
 }
}

結(jié)論

==Closure cannot implicitly capture a mutating self parameter錯(cuò)誤的原因是在進(jìn)出closure(閉包)之后,self的一致性沒(méi)辦法得到保證,所以編譯器默認(rèn)不允許在struct的closure(閉包)中使用self。如果我們確定這么做是安全的,就可以通過(guò)上面的兩種方式解決這個(gè)問(wèn)題。其中,方法二的性能更好一些。==

注意

這里可以記一下指針和swift變量之間的關(guān)系:

  • UnsafePointer對(duì)應(yīng)let
  • UnsafeMutablePointer對(duì)應(yīng)var
  • AutoreleasingUnsafeMutablePointer對(duì)應(yīng)unowned UnsafeMutablePointer,用于inout的參數(shù)類(lèi)型
  • UnsafeRawPointer對(duì)應(yīng)let Any,raw系列都是對(duì)應(yīng)相應(yīng)的Any類(lèi)型
  • UnsafeBufferPointer是non-owning的類(lèi)型(unowned),用于collection的elements, buffer系列均如此

3-2. Declarations from extensions cannot be overridden yet 錯(cuò)誤

==這個(gè)錯(cuò)誤大致是因?yàn)?協(xié)議方法是在extension里面的,不能被重寫(xiě)==

解決辦法:(僅供參考,如有更好的建議還望多多指教)

小編想到的解決辦法就是在每一個(gè)需要此協(xié)議的類(lèi)里面,重新遵循代理,實(shí)現(xiàn)該協(xié)議方法

3-3. "Method 'initialize()' defines Objective-C class method 'initialize', which is not permitted by Swift"

==報(bào)錯(cuò)原因: 在于已經(jīng)廢棄的initialize方法,示例如下==

方法交叉(Method Swizzling)

有時(shí)為了方便,也有可能是解決某些框架內(nèi)的 bug,或者別無(wú)他法時(shí),需要修改一個(gè)已經(jīng)存在類(lèi)的方法的行為。方法交叉可以讓你交換兩個(gè)方法的實(shí)現(xiàn),相當(dāng)于是用你寫(xiě)的方法來(lái)重載原有方法,并且還能夠是原有方法的行為保持不變。

extension UIViewController {
 public override class func initialize() {//此處報(bào)錯(cuò)
  
 //此處省略100行代碼
  
 }
}

initialize該方法已經(jīng)被Swift4.0廢棄

在Swift3.0還勉強(qiáng)可以使用,但是會(huì)有警告;但是在4.0已經(jīng)被完全廢棄

==替代方法:==

在 app delegate 中實(shí)現(xiàn)方法交叉

像上面通過(guò)類(lèi)擴(kuò)展進(jìn)行方法交叉,而是簡(jiǎn)單地在 app delegate 的 application(_:didFinishLaunchingWithOptions:) 方法調(diào)用時(shí)調(diào)用該方法

extension UIViewController {
 public override class func initializeOnceMethod() {
  
 //此處省略100行代碼
  
 }
}

//在AppDelegate的方法中調(diào)用:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
 //此處省略100行代碼
 UIViewController.initializeOnceMethod()

}

3-4. 'dispatch_once' is unavailable in Swift: Use lazily initialized globals instead

報(bào)錯(cuò)原因: dispatch_once在Swift4.0也已經(jīng)被廢棄

extension UITableView {
 struct once{
  static var onceTaken:Int = 0
 }
 dispatch_once(&once.onceTaken) { () -> Void in
 //在這里dispatch_once就會(huì)報(bào)錯(cuò)
  //此處省略1000000行代碼 
 }
}

解決方法: 通過(guò)給DispatchQueue添加擴(kuò)展實(shí)現(xiàn)

extension DispatchQueue {
 private static var _onceTracker = [String]()
 public class func once(token: String, block: () -> ()) {
  objc_sync_enter(self)
  defer {
   objc_sync_exit(self)
  }
  if _onceTracker.contains(token) {
   return
  }
  _onceTracker.append(token)
  block()
 }
 
 func async(block: @escaping ()->()) {
  self.async(execute: block)
 }
 
 func after(time: DispatchTime, block: @escaping ()->()) {
  self.asyncAfter(deadline: time, execute: block)
 }
}

使用字符串token作為once的ID,執(zhí)行once的時(shí)候加了一個(gè)鎖,避免多線程下的token判斷不準(zhǔn)確的問(wèn)題。
使用的時(shí)候可以傳token

 DispatchQueue.once(token: "tableViewOnce") {
  print( "Do This Once!" ) 
 }

或者使用UUID也可以:

private let _onceToken = NSUUID().uuidString
 
DispatchQueue.once(token: _onceToken) { 
 print( "Do This Once!" ) 
}

四、swift3.2升級(jí)到swift4.0 掃碼不走回調(diào)方法

xcode升級(jí)到9.0 swift改到swift4.0之后掃碼一直不走回調(diào) ,研究了好長(zhǎng)時(shí)間,發(fā)現(xiàn)蘋(píng)果把掃碼的代理方法的參數(shù)變了之前的方法

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!)

這是之前swift3.2的代理方法,swift4.0之后不會(huì)走這兩個(gè)代理方法,原因是現(xiàn)在代理方法不一樣了

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)

swift4.0的兩個(gè)代理方法對(duì)比之前的3.2方法,可以發(fā)現(xiàn)現(xiàn)在方法的參數(shù)變了

將之前的兩個(gè)方法的參數(shù)改好,掃碼就可以正常用了

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Swift重構(gòu)自定義空等運(yùn)算符 “??=” 實(shí)例

    Swift重構(gòu)自定義空等運(yùn)算符 “??=” 實(shí)例

    這篇文章主要為大家介紹了Swift重構(gòu)自定義空等運(yùn)算符 “??=” 實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 詳細(xì)講解Swift中的類(lèi)型占位符

    詳細(xì)講解Swift中的類(lèi)型占位符

    類(lèi)型占位符是swift5.6中引?的?個(gè)新功能,在處理稍微復(fù)雜的通?類(lèi)型時(shí),它可能真的很有用,這篇文章主要給大家介紹了關(guān)于Swift類(lèi)型占位符的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 詳解Swift編程中的常量和變量

    詳解Swift編程中的常量和變量

    這篇文章主要介紹了Swift編程中的常量和變量,是Swift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Swift中動(dòng)態(tài)調(diào)用實(shí)例方法介紹

    Swift中動(dòng)態(tài)調(diào)用實(shí)例方法介紹

    這篇文章主要介紹了Swift中動(dòng)態(tài)調(diào)用實(shí)例方法介紹,在Swift中有一類(lèi)很有意思的寫(xiě)法,可以讓我們不直接使用實(shí)例來(lái)調(diào)用這個(gè)實(shí)例上的方法,而是通過(guò)類(lèi)型取出這個(gè)類(lèi)型的某個(gè)實(shí)例方法的簽名,然后再通過(guò)傳遞實(shí)例來(lái)拿到實(shí)際需要調(diào)用的方法,需要的朋友可以參考下
    2015-01-01
  • swift中defer的實(shí)際應(yīng)用小結(jié)

    swift中defer的實(shí)際應(yīng)用小結(jié)

    這篇文章主要給大家介紹了關(guān)于swift中defer的實(shí)際應(yīng)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Swift中閉包實(shí)戰(zhàn)案例詳解

    Swift中閉包實(shí)戰(zhàn)案例詳解

    接觸過(guò)Swift的小伙伴對(duì)“閉包”應(yīng)該不陌生,相當(dāng)于OC中的Block,是Swift語(yǔ)法中比較難理解的一塊。下面這篇文章主要介紹了關(guān)于Swift中閉包實(shí)戰(zhàn)的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-03-03
  • swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能

    swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能

    這篇文章主要介紹了swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Swift 4中一些實(shí)用的數(shù)組技巧小結(jié)

    Swift 4中一些實(shí)用的數(shù)組技巧小結(jié)

    這篇文章主要給大家分享了關(guān)于Swift 4中一些實(shí)用的數(shù)組技巧,文中通過(guò)示例代碼介紹的介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Swift與Objective C的簡(jiǎn)單對(duì)比

    Swift與Objective C的簡(jiǎn)單對(duì)比

    很多人想學(xué)習(xí)iOS開(kāi)發(fā),但是不知道如何從Objective-C和Swift之間選擇。而網(wǎng)上的一些答案,大抵說(shuō)的是,以后Swift終將取代Objective-C,但是目前來(lái)講還是Objective-C比較重要。那么究竟怎樣呢,今天我們就來(lái)探討下
    2016-12-12
  • Swift5中fileprivate與private的差別淺析

    Swift5中fileprivate與private的差別淺析

    這篇文章主要給大家介紹了關(guān)于Swift5中fileprivate與private的差別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Swift5具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評(píng)論

新乡市| 三台县| 玉田县| 铜山县| 诸城市| 嘉兴市| 阳原县| 阿克| 手游| 西吉县| 固安县| 陵水| 高碑店市| 宝山区| 红原县| 望奎县| 含山县| 厦门市| 新民市| 广灵县| 安新县| 和平区| 鄂伦春自治旗| 长丰县| 鹿泉市| 镇江市| 芦溪县| 四会市| 德兴市| 西和县| 阜平县| 镇宁| 贵定县| 沙田区| 三门县| 鄂温| 娄底市| 双辽市| 建始县| 梅河口市| 绥阳县|