日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Swift項(xiàng)目兼容Objective-C問題匯總

一、解決問題

Swift項(xiàng)目需要使用封裝好的Objective-c組件、第三方類庫,蘋果提供的解決方案能夠處理日常大部分需求,但還不能稱之為完美,混編過程中會(huì)遇到很多問題。本文將Swift兼容Objective-c的問題匯總,以幫助大家更好的使用Swift,內(nèi)容列表如下:

1. Swift調(diào)用Objective-c代碼

2. Objective-c調(diào)用Swift代碼

3. Swift兼容Xib/Storyboard

4. Objective-c巧妙調(diào)用不兼容的Swift方法

5. 多Target編譯錯(cuò)誤解決

6. 第三方類庫支持

二、基礎(chǔ)混合編程

Swift與Objective-c的代碼相互調(diào)用,并不像Objective-c與C/C++那樣方便,需要做一些額外的配置工作。無論是Swift調(diào)用Objective-c還是Objective-c調(diào)用Swift,Xcode在處理上都需要兩個(gè)步驟:

2.1 Swift調(diào)用Objective-c代碼

Xcode對于Swift調(diào)用Objective-c代碼,除宏定義外,其它支持相對完善。

2.1.1 使用Objetvie-c的第一步

告訴Xcode、哪些Objective-c類要使用,新建.h頭文件,文件名可以任意取,建議采用“項(xiàng)目名-Bridging-Header.h”命令格式。

Tips

Swift之IOS項(xiàng)目,在Xcode6創(chuàng)建類文件,默認(rèn)會(huì)自動(dòng)選擇OS X標(biāo)簽下的文件,這時(shí)一定要選擇iOS標(biāo)簽下的文件,否則會(huì)出現(xiàn)語法智能提示不起作用,嚴(yán)重時(shí)會(huì)導(dǎo)致打包出錯(cuò)。

2.1.2 第二步,Target配置,使創(chuàng)建的頭文件生效

設(shè)置Objective-C Bridging Header時(shí),路徑要配置正確,例如:創(chuàng)建的名為“ILSwift-Bridging-Header.h”文件,存于ILSwift項(xiàng)目文件夾的根目錄下,寫法如下:

ILSwift/ILSwift-Bridging-Header.h

當(dāng)然,在新項(xiàng)目中,直接創(chuàng)建一個(gè)Objective-c類,Xcode會(huì)提示:

直接選擇Yes即可,如果不小心點(diǎn)了其它按鈕,可以按照上面的步驟一步一步添加。

2.2 Objective-c調(diào)用Swift代碼

2.2.1 Objective-c調(diào)用Swift代碼兩個(gè)步驟

第一步告訴Xcode哪些類需要使用(繼承自NSObject的類自動(dòng)處理,不需要此步驟),通過關(guān)鍵字@objc(className)來標(biāo)記

 
 
  1. import UIKit 
  2. @objc(ILWriteBySwift) 
  3. class ILWriteBySwift { 
  4. var name: String! 
  5. class func newInstance() -> ILWriteBySwift { 
  6. return ILWriteBySwift() 

第二步引入頭文件,Xcode頭文件的命名規(guī)則為

 
 
  1. $(SWIFT_MODULE_NAME)-Swift.h 

示例如下:
 

 
 
  1. #import "ILSwift-Swift.h" 

Tips

不清楚SWIFT_MODULE_NAME可通過以下步驟查看

#p#

2.2.2找不到$(SWIFT_MODULE_NAME)-Swift.h

1.遇到此問題可按以下步驟做常規(guī)性檢查

確定導(dǎo)入SWIFT_MODULE_NAME)-Swift.h頭文件的文件名正確

SWIFT_MODULE_NAME)-Swift.h在clean后沒有重新構(gòu)建,執(zhí)行Xcode->Product->Build

2.頭文件循環(huán)

在混合編程的項(xiàng)目中,由于兩種語言的同時(shí)使用,經(jīng)常會(huì)出現(xiàn)以下需求:在Swift項(xiàng)目中需要使用Objectvie-c寫的A類,而A類又會(huì)用到Swift的一些功能,頭文件的循環(huán),導(dǎo)致編譯器不能正確構(gòu)建$(SWIFT_MODULE_NAME)-Swift.h,遇到此問題時(shí),在.h文件做如下處理

 
 
  1. //刪除以下頭文件 
  2. //#import "ILSwift-Swift.h" 
  3. //通過代碼導(dǎo)入類 
  4. @class ILSwiftBean; 

在Objevtive-c的.m文件最上面,添加

 
 
  1. #import "ILSwift-Swift.h" 

出現(xiàn)Use of undecalared identifier錯(cuò)誤或者找不到方法,如下:

引起的原因有以下幾種可能:

使用的Swift類不是繼承自NSObject,加入關(guān)鍵字即可

SWIFT_MODULE_NAME)-Swift.h沒有實(shí)時(shí)更新,Xcode->Product->Build

此Swift文件中使用了Objective-c不支持的類型或者語法,如private

出現(xiàn)部分方法找不到的問題,Xcode無智能提示:

此方法使用了Objective-c不支持的類型或者語法

蘋果官方給出的不支持轉(zhuǎn)換的類型

Generics

Tuples

Enumerations defined in Swift

Structures defined in Swift

Top-level functions defined in Swift

Global variables defined in Swift

Typealiases defined in Swift

Swift-style variadics

Nested types

Curried functions

三、Xib/StoryBoard支持

Swift項(xiàng)目在使用Xib/StoryBoard時(shí),會(huì)遇到兩種不同的問題

Xib:不加載視圖內(nèi)容

Storyboard:找不到類文件

3.1 Xib不加載視圖內(nèi)容

在創(chuàng)建UIViewController時(shí),默認(rèn)選中Xib文件,在Xib與類文件名一致時(shí),可通過以下代碼實(shí)例化:
 

 
 
  1. let controller = ILViewController() 

運(yùn)行,界面上空無一物,Xib沒有被加載。解決辦法,在類的前面加上@objc(類名),例如:

 
 
  1. import UIKit 
  2. @objc(ILViewController) 
  3. class ILViewController: UIViewController { 

Tips:

StoryBoard中創(chuàng)建的UIViewController,不需要@objc(類名)也能夠保持兼容

3.2 Storyboard找不到類文件

Swift語言引入了Module概念,在通過關(guān)鍵字@objc(類名)做轉(zhuǎn)換的時(shí)候,由于Storboard沒有及時(shí)更新Module屬性,會(huì)導(dǎo)致如下兩種類型錯(cuò)誤:

3.2.1 用@objc(類名)標(biāo)記的Swift類或者Objective-c類可能出現(xiàn)錯(cuò)誤:

2015-06-02 11:27:42.626 ILSwift[2431:379047] Unknown class _TtC7ILSwift33ILNotFindSwiftTagByObjcController in Interface Builder file.

解決辦法,按下圖,選中Module中的空白,直接回車

3.2.2 無@objc(類名)標(biāo)記的Swift類

 
 
  1. 2015-06-02 11:36:29.788 ILSwift[2719:417490] Unknown class ILNotFindSwiftController in Interface Builder file. 

解決辦法,按下圖,選擇正確的Module

3.產(chǎn)生上面錯(cuò)誤的原因: 在設(shè)置好Storyboard后,直接在類文件中,添加或者刪除@objc(類名)關(guān)鍵字,導(dǎo)致Storyboard中 Module屬性沒有自動(dòng)更新,所以一個(gè)更通用的解決辦法是,讓Storyboard自動(dòng)更新Module,如下:

#p#

3.3 錯(cuò)誤模擬Demo下載

為了能夠讓大家更清楚的了解解決流程,將上面的錯(cuò)誤進(jìn)行了模擬,想動(dòng)手嘗試解決以上問題的同學(xué)可以直接下載demo

四、Objective-c巧妙調(diào)用不兼容的Swift方法

在Objective-c中調(diào)用Swift類中的方法時(shí),由于部分Swift語法不支持轉(zhuǎn)換,會(huì)遇到無法找到對應(yīng)方法的情況,如下:

 
 
  1. import UIKit 
  2. enum HTTPState { 
  3. case Succed, Failed, NetworkError, ServerError, Others 
  4. class ILHTTPRequest: NSObject { 
  5. class func requestLogin(userName: String, password: String, callback: (state: HTTPState) -> (Void)) { 
  6. dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in 
  7. NSThread.sleepForTimeInterval(3) 
  8. dispatch_async(dispatch_get_main_queue(), { () -> Void in 
  9. callback(state: HTTPState.Succed) 
  10. }) 
  11. }) 

對應(yīng)的$(SWIFT_MODULE_NAME)-Swift.h文件為:

 
 
  1. SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest") 
  2. @interface ILHTTPRequest : NSObject 
  3. - (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER; 
  4. @end 

從上面的頭文件中可以看出,方法requestLogin使用了不支持的Swift枚舉,轉(zhuǎn)換時(shí)方法被自動(dòng)忽略掉,有以下兩種辦法,可以巧妙解決類似問題:

4.1 用支持的Swift語法包裝

在Swift文件中,添加一個(gè)可兼容包裝方法wrapRequestLogin,注意此方法中不能使用不兼容的類型或者語法
 

 
 
  1. import UIKit 
  2. enum HTTPState: Int { 
  3. case Succed = 0, Failed = 1, NetworkError = 2, ServerError = 3, Others = 4 
  4. class ILHTTPRequest: NSObject { 
  5. class func requestLogin(userName: String, password: String, callback: (state: HTTPState) -> (Void)) { 
  6. dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in 
  7. NSThread.sleepForTimeInterval(3) 
  8. dispatch_async(dispatch_get_main_queue(), { () -> Void in 
  9. callback(state: HTTPState.Succed) 
  10. }) 
  11. }) 
  12. class func wrapRequestLogin(userName: String, password: String, callback: (state: Int) -> (Void)) { 
  13. self.requestLogin(userName, password: password) { (state) -> (Void) in 
  14. callback(state: state.rawValue) 

對應(yīng)的$(SWIFT_MODULE_NAME)-Swift.h文件為:

 
 
  1. SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest") 
  2. @interface ILHTTPRequest : NSObject 
  3. + (void)wrapRequestLogin:(NSString * __nonnull)userName password:(NSString * __nonnull)password callback:(void (^ __nonnull)(NSInteger))callback; 
  4. - (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER; 
  5. @end 

此時(shí),我們可以在Objective-c中直接使用包裝后的方法wrapRequestLogin

4.2 巧妙使用繼承

使用繼承可以支持所有的Swift類型,主要的功能在Objective-c中實(shí)現(xiàn),不支持的語法在Swift文件中調(diào)用,例如,ILLoginSuperController做為父類

 
 
  1. @interface ILLoginSuperController : UIViewController 
  2. @property (weak, nonatomic) IBOutlet UITextField *userNameField; 
  3. @property (weak, nonatomic) IBOutlet UITextField *passwordField; 
  4. - (IBAction)loginButtonPressed:(id)sender; 
  5. @end 
  6. //////////////////////////////////////////////////////////////// 
  7. @implementation ILLoginSuperController 
  8. - (IBAction)loginButtonPressed:(id)sender 
  9. @end 

創(chuàng)建Swift文件,繼承自ILLoginSuperController,在此Swift文件中調(diào)用那些不支持的語法

 
 
  1. import UIKit 
  2. class ILLoginController: ILLoginSuperController { 
  3. override func loginButtonPressed(sender: AnyObject!) { 
  4. ILHTTPRequest.requestLogin(self.userNameField.text, password: self.passwordField.text) { (state) -> (Void) in 
  5. //具體業(yè)務(wù)邏輯 

五、多Target編譯錯(cuò)誤解決

在使用多Target時(shí),會(huì)出現(xiàn)一些編譯錯(cuò)誤

5.1 Use of undeclared type

此類錯(cuò)誤,是因?yàn)楫?dāng)前運(yùn)行的Target找不到必須編譯文件。將文件添加到Target即可,如下支持ILSwiftTests Target,選中ILSwiftTests前的復(fù)選框即可

5.2 does not have a member named

此類錯(cuò)誤可能由于如下兩種原因引起,解決辦法同上:

1.此方法來自父類,父類文件沒有加入到當(dāng)前Target

2.此方法來自擴(kuò)展,擴(kuò)展沒有加入到當(dāng)前Target

Tips

如果檢查發(fā)現(xiàn),所有的類文件都已經(jīng)準(zhǔn)確添加到Target中,但編譯還是不通過,此時(shí)著重檢查橋接文件是否正確設(shè)置,是否將相應(yīng)的頭文件加入到了橋接文件中。如無特別要求,建議將所有Target的橋接文件全都指向同一文件。關(guān)于橋接文件的設(shè)置,請參考2.1

六、第三方類庫支持

Swift項(xiàng)目取消了預(yù)編譯文件,一些第三方Objective-c庫沒有導(dǎo)入必要框架(如UIKit)引起編譯錯(cuò)誤

6.1 Cocoapods找不到.o文件

在使用了Cocoapods項(xiàng)目中,會(huì)出現(xiàn)部分類庫的.o文件找不到,導(dǎo)致此種錯(cuò)誤主要是以下兩種問題:

類庫本身存在編譯錯(cuò)誤

Swift沒有預(yù)編譯,UIKit等沒有導(dǎo)入

將此庫文件中的代碼文件直接加到項(xiàng)目中,編譯,解決錯(cuò)誤。

6.2 JSONModel支持

在Swift中可以使用JSONModel部分簡單功能,一些復(fù)雜的數(shù)據(jù)模型建議使用Objevtive-c

 
 
  1. import UIKit 
  2. @objc(ILLoginBean) 
  3. public class ILLoginBean: JSONModel { 
  4. var userAvatarURL: NSString? 
  5. var userPhone: NSString! 
  6. var uid: NSString! 

Tips

在Swift使用JSONModel框架時(shí),字段只能是NSFoundation中的支持類型,Swift下新添加的String、Int、Array等都不能使用

6.3 友盟統(tǒng)計(jì)

Swift項(xiàng)目中引入友盟統(tǒng)計(jì)SDK會(huì)出現(xiàn)referenced from錯(cuò)誤:

解決辦法,找到Other Linker Flags,添加-lz

七、綜述

現(xiàn)在大部分成熟的第三方框架都是使用Objective-c寫的,開發(fā)時(shí)不可避免的涉及到兩種語言的混合編程,期間會(huì)遇到很多奇怪的問題。因?yàn)槲粗庞刑剿鞯膬r(jià)值,Swift的簡潔快速,能夠極大的推進(jìn)開發(fā)進(jìn)度。所以從今天開始,大膽的開始嘗試。


網(wǎng)頁題目:Swift項(xiàng)目兼容Objective-C問題匯總
轉(zhuǎn)載源于:http://www.dlmjj.cn/article/dhighcg.html