swift3.0和Objective-C的交互需要注意這些

前言:

swift3.0出來(lái)后, 可以看到改變很大, 和cocoa, Foundation...的交互也變得更方便了, 同時(shí)swift編寫的應(yīng)用適配到iOS7, 所以, 我們可以相信: 在未來(lái)使用swift的情況會(huì)逐漸增加了, 同時(shí)會(huì)涉及到oc和swift在項(xiàng)目中并存的情況, 這里我重新讀了官方的'Using swift with Cocoa and Objective-C(swift3)'的文檔, 記錄了一些個(gè)人覺(jué)得比較常用的筆記, 請(qǐng)大家選擇性閱讀(里面的代碼 均來(lái)自文檔)

  1. oc的初始化方法在swift中被引為
    init(...) --- 如果初始化不會(huì)失敗
    init?(...) --- 如果初始化可能失敗
    init!(...) --- 否則
  • oc中的property里的(getter==, setter==)將會(huì)被swift忽略
  • id對(duì)應(yīng)Anyobject 但是所有的Anyobject在swift中是可選值, 如果之前的值為可選值, 在被設(shè)置為Anyobject后就是多重可選值了
  • oc中的屬性被標(biāo)記為
    nullable -> 在swift中相當(dāng)于 ?
    nonnull -> 在swift中相當(dāng)于 非可選屬性
    未標(biāo)記 -> 在swift中相當(dāng)于 !
  • oc中的輕量級(jí)泛型也是對(duì)應(yīng)與swift中的泛型
    @property NSArray<NSDate *> *dates
    對(duì)應(yīng)于 var dates: [Date]
  • swift 中的閉包默認(rèn)捕獲變量的方式相當(dāng)于 oc中block中捕獲被標(biāo)記為 __block的變量方式 -> 就是說(shuō) 閉包捕獲到的是變量的指針
  • swift中只要不是在多線程中, 建議使用[unowned self]來(lái)避免循環(huán)引用, 多線程中, 建議使用[weak self]
  • == 操作符相當(dāng)于oc中的isEqual: --- 即比較內(nèi)容是否相等
    === 相當(dāng)于oc中的指針比較
  • 繼承自NSObject的子類如果重寫了isEquals: 方法, 應(yīng)當(dāng)提供 hash 這個(gè)屬性
  • 不能在oc中繼承swift的class
  • 如果在swift中遇到oc中不支持的命名 可以利用 @objc(name)為他(屬性 枚舉, 方法名...)名個(gè)別名
  • @nonobjc 用來(lái)標(biāo)記oc中不支持的
  • dynamic 將屬性或者方法標(biāo)記為dynamic就是告訴編譯器把它當(dāng)作oc里的屬性或方法來(lái)使用(runtime),
    當(dāng)需要使用 KVO 或者 runtime的時(shí)候需要這樣處理
  • 當(dāng)使用oc的 perform(selector, with:)方法的時(shí)候 會(huì)返回一個(gè)可選值(指向AnyObject的指針)
    但是使用perform(:on:with:waitUntilDone:modes:) and perform(:with:afterDelay:)不會(huì)返回可選值
  • 使用 #keyPath() 可以轉(zhuǎn)換為string, #keyPath(class.property) == "property"
    可用于KVC 例如person.value(forKey: #keyPath(Person.name)) = person.name
    但是測(cè)試了下不能修改swift中的只讀屬性 不知道有什么方便的用處
  • NSClassFromString("MyFramework.MyClass")
  • @IBDesignable 用在class(UIView的子類)聲明的前面, 然后就可以在storyBoard中的inspector編輯它
    @IBInspectable 用在(UIView的子類)的屬性前面, 然后就可以在storyBoard中的inspector編輯它 ,就想系統(tǒng)提供的可以設(shè)置顏色,字體...
  • swift中的屬性默認(rèn)是strong類型, 只有可選類型才能被標(biāo)記為weak
    oc中的 copy屬性 轉(zhuǎn)換為swift中的@NSCopying 必須遵守NSCoding協(xié)議
  • 使用Core Data的時(shí)候所有的屬性和方法需要標(biāo)記為 @NSManaged
  • 文檔中指出"The corresponding reference types can be accessed with their original NS class name prefix."
    但是beta版本中不能很好的使用NS開頭的
  • 在oc和swift的橋接類型之間 直接使用 as 可以相互轉(zhuǎn)換
  • 因?yàn)閟wift中的String和NSString使用的編碼方式不一樣,
    所以在swift中要對(duì)string使用索引的時(shí)候 不能直接使用 Int 或者NSRange
    需要使用String.Index and Range<String.Index>
  • swift會(huì)將Double, Int, Bool, Uint, Float和NSNumber橋接, 所以可以直接將
    這些類型的值使用 as NSNumber轉(zhuǎn)換為NSNumber, 但是逆向進(jìn)行是得到的可選值 as?
  • Foundation 和Core Foundation 之間的類型有toll-free bridge('免費(fèi)橋')
  • Foundation中的常量, 在swift中被換為類嵌套的枚舉
    NSJSONReadingOptions ----- >> JSONSerialization.ReadingOption
  • swift中使用 Core Foundation
    • 如果使用swift處理過(guò)的函數(shù)不用我們手動(dòng)管理內(nèi)存分配
    • 否則需要我們處理
    • 區(qū)分的方式: 當(dāng)返回值是 Unmanaged<Instance>的時(shí)候說(shuō)明需要我們處理
    • 處理方法: 在使用返回的值之前調(diào)用他對(duì)應(yīng)的takeUnretainedValue() 或
      takeRetainedValue()即可
    • 例如let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
  • swift中Core Foundation里的類型 Ref后綴被去掉了 例如 CFTypeRef -> CFType
  • 在oc的方法 使用 NS_SWIFT_NOTHROW , 將不會(huì)使用swift的異常拋出機(jī)制
  • swift中直接使用 is 來(lái)實(shí)現(xiàn)oc中isKindOfClass: 的功能
  • swift中使用kvo的條件: 1.必須繼承自NSObject 2. 被觀察的屬性 要被標(biāo)記為 dynamic
  • swift 中的單例很簡(jiǎn)單:
class Singleton {
   static let sharedInstance = Singleton()
} 
或者
class Singleton {
   static let sharedInstance: Singleton = {
       let instance = Singleton()
       // setup code
       return instance
   }()
}
  • swift和C的交互: c的函數(shù)在swift中均為全局函數(shù)
  • 使用CF_SWIFT_NAME 這個(gè)宏可以將c中的屬性或者函數(shù)轉(zhuǎn)換為swift中
    eg:
Color ColorCreateWithCMYK(float c, float m, float y, float k) CF_SWIFT_NAME(Color.init(c:m:y:k:));  
對(duì)應(yīng)為swift中
extension Color {
    init(c: Float, m: Float, y: Float, k: Float)
}
  • c語(yǔ)言中的枚舉 如果使用了NS_ENUM定義, 則在swift中被處理為對(duì)應(yīng)的枚舉
    如果沒(méi)有使用NS_ENUM定義, 則被處理為結(jié)構(gòu)體
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
   UITableViewCellStyleDefault,
   UITableViewCellStyleValue1,
   UITableViewCellStyleValue2,
   UITableViewCellStyleSubtitle
};
//對(duì)應(yīng)與
enum UITableViewCellStyle: Int {
    case `default`
    case value1
    case value2
    case subtitle
}
typedef enum {
   MessageDispositionUnread = 0,
   MessageDispositionRead = 1,
   MessageDispositionDeleted = -1,
} MessageDisposition;
對(duì)應(yīng)與
struct MessageDisposition: RawRepresentable, Equatable {}
var MessageDispositionUnread: MessageDisposition { get }
var MessageDispositionRead: MessageDisposition { get }
var MessageDispositionDeleted: MessageDisposition { get }
  • c中的被NS_OPTIONS修飾的枚舉, 在swift中是OptionSet類型, -> 即可以使用數(shù)組方式選多個(gè)值
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone                 = 0,
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
        UIViewAutoresizingFlexibleWidth        = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
        UIViewAutoresizingFlexibleHeight       = 1 << 4,
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
對(duì)應(yīng)與
public struct UIViewAutoresizing : OptionSet {
    public init(rawValue: UInt)
    
    public static var flexibleLeftMargin: UIViewAutoresizing { get }
    public static var flexibleWidth: UIViewAutoresizing { get }
    public static var flexibleRightMargin: UIViewAutoresizing { get }
    public static var flexibleTopMargin: UIViewAutoresizing { get }
    public static var flexibleHeight: UIViewAutoresizing { get }
    public static var flexibleBottomMargin: UIViewAutoresizing { get }
}
在swift中直接使用  let resize = [. flexibleLeftMargin, . flexibleWidth...]
  • 在swift中全局變量和存儲(chǔ)屬性都被保證只初始化一次,
    • 所以用來(lái)當(dāng)作OC里面的#define定義的常量
    • 同時(shí)swift全局函數(shù)可以當(dāng)作OC里#define定義的復(fù)雜宏(類似函數(shù))
  • swift中的條件編譯 自定義編譯符的方法(例如: DEBUG_LOGGING)
    • 首先在project 的設(shè)置里面設(shè)置swift -D DEBUG_LOGGING to set the DEBUG_LOGGING
    • 然后使用 #if DEBUG_LOGGING // 操作 #endif
#if arch(arm) || arch(arm64)
#if swift(>=3.0)
print("Using Swift 3 ARM code")
    #else
    print("Using Swift 2.2 ARM code")
#endif
#elseif arch(x86_64)
print("Using 64-bit x86 code.)
    #else
    print("Using general code.")
#endif
  • swift中使用指針的方式
    • 使用inout方式 &變量
    • 使用UnsafePointer<Type> 或者UnsafeMutablePointer<Type>
例如這個(gè)函數(shù)接受的參數(shù)可以傳許多種
let x: Float = 0
func takesAPointer(_ p: UnsafePointer<Float>!) {
    // ...
}
takesAPointer(&x)
takesAPointer([0.0,1.0])
  • 在swift中申明oc中的包含可選實(shí)現(xiàn)方法的協(xié)議時(shí)需要在協(xié)議和方法前都標(biāo)記objc
@objc public protocol MySwiftProtocol {
// 必須實(shí)現(xiàn)
    func requiredMethod()
    
    @objc optional func optionalMethod()
}
  • 將oc的方法或者屬性使用NS_SWIFT_NAME()可以為他們?cè)趕wift中命一個(gè)別名
  • 將oc的方法或使用 NS_SWIFT_UNAVAILABLE()可以讓他在swift中不可用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容