[翻]如何將您的APP從Objective C轉移到Swift?

CNKCQ發表於2018-12-16

自從蘋果在2014年釋出了自己的Swift程式語言之後,很多開發人員都利用這個機會來測試它的特性,看看它是如何與Objective-C進行比較的。 一般結論似乎是: 在某些情況下,Swift比Objective-C更可取。
###Swift的優點是什麼?

  1. Swift允許你編寫較少的程式碼。
  2. Swift是強型別的,這意味著更少的處理型別不正確導致崩潰。
  3. Swift看起來類似於其他流行的程式語言,類似於英語。
  4. Swift比它的前任Objective-C快。

這些功能使Swift非常誘人。 讓我們考慮如果你決定從Objective-C切換到Swift你需要做什麼,並確定是否應該轉移到Swift上。
值得一提的是,Swift與Objective-C完全相容。 Apple提供了一個混合和匹配功能,允許開發人員在同一個專案中使用這兩種語言。 這意味著您可以向現有的程式碼庫新增新的Swift功能。 同時,儘管Swift和Objective-C使用相同的API,但在從Objective-C遷移到Swift時,您必須記住一些差異。

###Optional 型別

在Objective-C中,你可以呼叫nil物件的方法(更準確地說,你可以傳送訊息到nil物件),這些方法返回一個空值。為了防止在出現意外的nil值時出現未定義的行為,您需要在需要時執行nil檢查。 Swift引入了可選值的概念。可選型別宣告為類似列舉:

public enum可選<Wrapped>:_Reflectable,NilLiteralConvertible
複製程式碼

從程式設計上來說,它是一種型別,可以代表Wrapped型別的值或不存在的值。 Swift提供了使型別可選的語法糖,所以不需要宣告Optional ,你可以只寫String?您有兩個選項從可選容器獲取包裝的值。第一個是可選連結 – if-let條件語句僅當它存在時才接收該值。如果您完全確定可選變數是非零,您可以使用強制解包。這提供了儲存的值,如果存在,沒有條件,但是當你犯了一個錯誤,並且可選例項為空時崩潰。
除了常規可選項,還有隱含的展開可選項,宣告為String!讓我們來看看你可以用不同的方式宣告可選性。

class ExampleClass {   
    var nonOptionalString: String   
    var unwrappedOptionalString: String!   
    var optionalString: String?  
    init(string: String) {       
    nonOptionalString = string
   }
}
複製程式碼

nonOptionalString永遠不能為nil。 此屬性應在物件初始化期間填充。 提供強制解包的nil物件將導致崩潰。
unwrappedOptionalString可以是nil,但如果您嘗試訪問nil物件,您的程式將崩潰。
optionalString可以為nil,應被視為常規可選變數。
當編寫Objective-C程式碼時,可以使用_Nullable和_Nonnull型別註釋來標記變數。 上面的Swift示例的Objective-C等價類似於:

 @interface ExampleClass: NSObject
 @property (nonatomic, strong) NSString * _Nonnull nonOptionalString;
 @property (nonatomic, strong) NSString *unwrappedOptionalString;  
 @property (nonatomic, strong) NSString * _Nullable optionalString;
 - (instancetype)initWithString:(nonnull NSString *string);
 @end
複製程式碼

###錯誤處理

當在Objective-C中丟擲和處理錯誤時,方法的最後一個引數是對NSError變數的引用。 如果此方法執行導致不可接受的行為,則應建立一個NSError例項並將其寫入傳遞的變數。 在呼叫可能產生錯誤的方法後,您應該檢查錯誤引數,以確保它是非零。

- (nonnull NSString *)exampleMethod:(nonnull NSString *)param error:(NSError **)error { 
    if (!param.length) {       
            *error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier                         
           code:-101                               
           userInfo:nil];       
    return nil; 
  }   // do work}
複製程式碼

Objective-C還提供了一個具有傳統try-catch-finally語法的異常機制,但是Apple強烈建議僅將其用於開發目的。
Swift要求您標記使用throws關鍵字生成錯誤的方法。 如果該方法接受的最後一個引數是指向Objective-C介面中的NSError例項的指標,那麼它將從Objective-C翻譯為Swift作為throwing方法,上面方法的宣告將轉換為 :

func exampleMethod(param:String)throws - > String
複製程式碼

Objective-C允許你省略錯誤處理的錯誤返回方法,但在Swift你必須明確處理錯誤。 被丟擲的物件應該是Swift ErrorType的後代。
###列舉

Objective-C提供C風格的列舉,它只限於基本型別。 即使您需要將整數列舉值對映到相應的字串以顯示給使用者或傳送到後端,也必須建立陣列或字典 – 或使用switch語句。 但Swift提供了全新的列舉與更多的選擇。 Swift中的列舉可以按照與Objective-C中相同的方式使用:

enum ExampleEnum {  
    case ExOne, ExTwo, ExThree  
}
複製程式碼

Swift列舉可以儲存關聯的值。 每個列舉大小寫都可以包含一組預定義的欄位。

enum AnotherExampleEnum {   
   case ExOne(String, Int)  
   case ExTwo(Int)
}
複製程式碼

Swift列舉可以儲存原始值並遞迴。
Swift還有各種強大的功能,它與Objective-C區別開來。 這些功能包括泛型,嚴格型別系統,型別推斷,元組和巢狀型別。 簡而言之,從Objective-C遷移到Swift不是一件小事。 這裡有一些提示,使過程更容易。
###從Objective-C遷移到Swift的提示

首先,您應該建立一個與相應頭和實現檔名稱相同的.swift檔案。 如果你需要從新的Swift檔案中訪問Objective-C類,你必須為它們新增一個import指令到橋接標頭檔案。 如果你需要從Objective-C程式碼訪問新的Swift類,你必須從Objective-C類繼承它; 否則將無法訪問。 然後你必須手動重寫程式碼,採用Swift的最佳實踐並使類向下相容。
如果你的Google“從Objective-C遷移到Swift”,你會發現幾個連結,建議自動翻譯程式碼的工具。 有免費和付費解決方案。 然而,即使付費的解決方案在它們的功能上極其有限。
為了看看這些工具是如何在Objective-C中建立一個非常基本的遊戲,然後嘗試使用幾個自動翻譯器將它翻譯成Swift。我們嘗試的第一個是基於Web的,並允許您上傳一個完整的Xcode專案(但是隻有當專案小於10 MB)。結果真的沒有準備好生產 – 我們發現超過70個錯誤,即使我們的程式只有7個小類。這些錯誤包括不正確的可選,不正確的型別推斷,留下最後一個引數為NSError,而不是切換到Swift錯誤處理與try-catch,從__weak不正確切換typeof(self)weakSelf = self;到[weak self]等。我們還測試了一個付費桌面應用程式,花費15美元,但結果更糟。我們測試的桌面應用程式無法匯入整個專案,因此我們不得不按檔案複製和貼上所有檔案。
行業中的大多數人都同意Swift正在成為iOS開發的主要語言,因此建議將它用於新專案。
方便地是,混合和匹配特性允許您使用Swift和Objective-C類作為同一專案的一部分,因此您不必花費時間重寫Swift中的整個現有程式碼庫。

相關文章