亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Swift > 正文

Swift調用Objective-C編寫的API實例

2020-03-09 17:52:13
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Swift調用Objective-C編寫的API實例,介紹的比較全面和詳細,對Objective-C代碼的重復利用有極大好處,的朋友可以參考下
 

互用性是讓 Swift 和 Objective-C 相接合的一種特性,使你能夠在一種語言編寫的文件中使用另一種語言。當你準備開始把 Swift 融入到你的開發流程中時,你應該懂得如何利用互用性來重新定義并提高你寫 Cocoa 應用的方案。

互用性很重要的一點就是允許你在寫 Swift 代碼時使用 Objective-C 的 API 接口。當你導入一個 Objective-C 框架后,你可以使用原生的 Swift 語法實例化它的 Class 并且與之交互。

初始化

為了使用 Swift 實例化 Objective-C 的 Class,你應該使用 Swift 語法調用它的一個初始化器。當 Objective-C 的init方法變化到 Swift,他們用 Swift 初始化語法呈現。“init”前綴被截斷當作一個關鍵字,用來表明該方法是初始化方法。那些以“initWith”開頭的init方法,“With”也會被去除。從“init”或者“initWith”中分離出來的這部分方法名首字母變成小寫,并且被當做是第一個參數的參數名。其余的每一部分方法名依次變味參數名。這些方法名都在圓括號中被調用。

舉個例子,你在使用 Objective-C 時會這樣做:

復制代碼代碼如下:

//Objective-C
UITableView *myTableView = [[UITableView alloc]
initWithFrame:CGRectZero style:UITableViewStyleGrouped];

 

在 Swift 中,你應該這樣做:

復制代碼代碼如下:

//Swift
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped) 

 

你不需要調用 alloc,Swift 能替你處理。注意,當使用 Swift 風格的初始化函數的時候,“init”不會出現。
你可以在初始化時顯式的聲明對象的類型,也可以忽略它,Swift 能夠正確判斷對象的類型。

復制代碼代碼如下:

//Swift
let myTextField = UITextField(frame: CGRect(0.0, 0.0, 200.0, 40.0)) 

 

這里的UITableView和UITextField對象和你在 Objective-C 中使用的具有相同的功能。你可以用一樣的方式使用他們,包括訪問屬性或者調用各自的類中的方法。
為了統一和簡易,Objective-C 的工廠方法也在 Swift 中映射為方便的初始化方法。這種映射能夠讓他們使用同樣簡潔明了的初始化方法。例如,在 Objective-C 中你可能會像下面這樣調用一個工廠方法:

復制代碼代碼如下:

//Objective-C
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0]; 

 

在 Swift 中,你應該這樣做:

復制代碼代碼如下:

//Swift
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0) 

 

訪問屬性

在 Swift 中訪問和設置 Objective-C 對象的屬性時,使用點語法:

復制代碼代碼如下:

// Swift
myTextField.textColor = UIColor.darkGrayColor()
myTextField.text = "Hello world"
if myTextField.editing {
    myTextField.editing = false
}

 

當 get 或 set 屬性時,直接使用屬性名稱,不需要附加圓括號。注意,darkGrayColor后面附加了一對圓括號,這是因為darkGrayColor是UIColor的一個類方法,不是一個屬性。

在 Objective-C 中,一個有返回值的無參數方法可以被作為一個隱式的訪問函數,并且可以與訪問器使用同樣的方法調用。但在 Swift 中不再能夠這樣做了,只有使用@property關鍵字聲明的屬性才會被作為屬性引入。

方法

在 Swift 中調用 Objective-C 方法時,使用點語法。

當 Objective-C 方法轉換到 Swift 時,Objective-C 的selector的第一部分將會成為方法名并出現在圓括號的前面,而第一個參數將直接在括號中出現,并且沒有參數名,而剩下的參數名與參數則一一對應的填入圓括號中。

舉個例子,你在使用 Objective-C 時會這樣做:

復制代碼代碼如下:

//Objective-C
[myTableView insertSubview:mySubview atIndex:2]; 

 

在 Swift 中,你應該這樣做:

復制代碼代碼如下:

//Swift
myTableView.insertSubview(mySubview, atIndex: 2) 

 

如果你調用一個無參方法,仍必須在方法名后面加上一對圓括號

復制代碼代碼如下:

//Swift
myTableView.layoutIfNeeded() 

 

id 兼容性(id Compatibility)

Swift 包含一個叫做AnyObject的協議類型,表示任意類型的對象,就像 Objective-C 中的id一樣。AnyObject協議允許你編寫類型安全的 Swift 代碼同時維持無類型對象的靈活性。因為AnyObject協議保證了這種安全,Swift 將 id 對象導入為 AnyObject。

舉個例子,跟 id 一樣,你可以為AnyObject類型的對象分配任何其他類型的對象,你也同樣可以為它重新分配其他類型的對象。

 

復制代碼代碼如下:

//Swift
var myObject: AnyObject = UITableViewCell()
myObject = NSDate() 

 

你也可以在調用 Objective-C 方法或者訪問屬性時不將它轉換為具體類的類型。這包括了 Objcive-C 中標記為 @objc 的方法。

復制代碼代碼如下:

//Swift
let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow 

 

然而,由于直到運行時才知道AnyObject的對象類型,所以有可能在不經意間寫出不安全代碼。另外,與 Objective-C 不同的是,如果你調用方法或者訪問的屬性 AnyObject 對象沒有聲明,將會報運行時錯誤。比如下面的代碼在運行時將會報出一個 unrecognized selector error 錯誤:

復制代碼代碼如下:

//Swift
myObject.characterAtIndex(5)
// crash, myObject does't respond to that method 

 

但是,你可以通過 Swift 的 optinals 特性來排除這個 Objective-C 中常見的錯誤,當你用AnyObject對象調用一個 Objective-C 方法時,這次調用將會變成一次隱式展開 optional(implicitly unwrapped optional)的行為。你可以通過 optional 特性來決定 AnyObject 類型的對象是否調用該方法,同樣的,你可以把這種特性應用在屬性上。

舉個例子,在下面的代碼中,第一和第二行代碼將不會被執行因為length屬性和characterAtIndex:方法不存在于 NSDate 對象中。myLength常量會被推測成可選的Int類型并且被賦值為nil。同樣你可以使用if-let聲明來有條件的展開這個方法的返回值,從而判斷對象是否能執行這個方法。就像第三行做的一樣。

復制代碼代碼如下:

//Swift
let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found /(fifthCharacter) at index 5")
}

 

對于 Swift 中的強制類型轉換,從 AnyObject 類型的對象轉換成明確的類型并不會保證成功,所以它會返回一個可選的值。而你需通過檢查該值的類型來確認轉換是否成功。

復制代碼代碼如下:

//Swift
let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefaults.objectForKey("LastRefreshDate")
if let date = lastRefreshDate as? NSDate {
    println("/(date.timeIntervalSinceReferenceDate)")
}

 

當然,如果你能確定這個對象的類型(并且確定不是nil),你可以添加as操作符強制調用。

復制代碼代碼如下:

//Swift
let myDate = lastRefreshDate as NSDate
let timeInterval = myDate.timeIntervalSinceReferenceDate 

 

使用nil

在Objective-C中,對象的引用可以是值為NULL的原始指針(同樣也是Objective-C中的nil)。而在Swift中,所有的值–包括結構體與對象的引用–都被保證為非空。作為替代,你將這個可以為空的值包裝為optional type。當你需要宣告值為空時,你需要使用nil。你可以在Optionals中了解更多。

因為Objective-C不會保證一個對象的值是否非空,Swift在引入Objective-C的API的時候,確保了所有函數的返回類型與參數類型都是optional,在你使用Objective-C的API之前,你應該檢查并保證該值非空。 在某些情況下,你可能絕對確認某些Objective-C方法或者屬性永遠不應該返回一個nil的對象引用。為了讓對象在這種情況下更加易用,Swift使用 implicitly unwrapped optionals 方法引入對象, implicitly unwrapped optionals 包含optional 類型的所有安全特性。此外,你可以直接訪問對象的值而無需檢查nil。當你訪問這種類型的變量時, implicitly unwrapped optional 首先檢查這個對象的值是否不存在,如果不存在,將會拋出運行時錯誤。

擴展(Extensions)

Swift 的擴展和 Objective-C 的類別(Category)相似。擴展為原有的類,結構和枚舉豐富了功能,包括在 Objective-C 中定義過的。你可以為系統的框架或者你自己的類型增加擴展,只需要導入合適的模塊并且保證你在 Objective-C 中使用的類、結構或枚舉擁有相同的名字。

舉個例子,你可以擴展UIBezierPath類來為它增加一個等邊三角形,這個方法只需提供三角形的邊長與起點。

復制代碼代碼如下:

//Swift
extension UIBezierPath {
    convenience init(triangleSideLength: Float, origin: CGPoint) {
        self.init()
        let squareRoot = Float(sqrt(3))
        let altitude = (squareRoot * triangleSideLength) / 2
        moveToPoint(origin)
        addLineToPoint(CGPoint(triangleSideLength, origin.x))
        addLineToPoint(CGPoint(triangleSideLength / 2, altitude))
        closePath()
    }
}

 

你也可以使用擴展來增加屬性(包括類的屬性與靜態屬性)。然而,這些屬性必須是通過計算才能獲取的,擴展不會為類,結構體,枚舉存儲屬性。下面這個例子為CGRect類增加了一個叫area的屬性。

復制代碼代碼如下:

//Swift
extension CGRect {
    var area: CGFloat {
    return width * height
    }
}
let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0)
let area = rect.area
// area: CGFloat = 500.0

 

你同樣可以使用擴展來為類添加協議而無需增加它的子類。如果這個協議是在 Swift 中被定義的,你可以添加 comformance 到它的結構或枚舉中無論它們在 Objective-C 或在 Swift 中被定義。

你不能使用擴展來覆蓋 Objective-C 類型中存在的方法與屬性。

閉包(Closures)

Objective-C 中的blocks會被自動導入為 Swift 中的閉包。例如,下面是一個 Objective-C 中的 block 變量:

復制代碼代碼如下:

//Objective-C
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */} 

 

而它在 Swift 中的形式為

復制代碼代碼如下:

//Swift
let completionBlock: (NSData, NSError) -> Void = {data, error in /* ... */} 

 

Swift 的閉包與 Objective-C 中的 blocks 能夠和睦相處,所以你可以把一個 Swift 閉包傳遞給一個把 block 作為參數的 Objective-C 函數。Swift 閉包與函數具有互通的類型,所以你甚至可以傳遞 Swift 函數的名字。
閉包與 blocks 語義上想通但是在一個地方不同:變量是可以直接改變的,而不是像 block 那樣會拷貝變量。換句話說,Swift 中變量的默認行為與 Objective-C 中 __block 變量一致。

比較對象

當比較兩個 Swift 中的對象時,可以使用兩種方式。第一種,使用(==),判斷兩個對象內容是否相同。第二種,使用(===),判斷常量或者變量是否為同一個對象的實例。

Swift 與 Objective-C 一般使用 == 與 === 操作符來做比較。Swift 的 == 操作符為源自 NSObject 的對象提供了默認的實現。在實現 == 操作符時,Swift 調用 NSObject 定義的 isEqual: 方法。

NSObject 類僅僅做了身份的比較,所以你需要在你自己的類中重新實現 isEqual: 方法。因為你可以直接傳遞 Swift 對象給 Objective-C 的 API,你也應該為這些對象實現自定義的 isEqual: 方法,如果你希望比較兩個對象的內容是否相同而不是僅僅比較他們是不是由相同的對象派生。

作為實現比較函數的一部分,確保根據Object comparison實現對象的hash屬性。更進一步的說,如果你希望你的類能夠作為字典中的鍵,也需要遵從Hashable協議以及實現hashValues屬性。

Swift 類型兼容性

當你定義了一個繼承自NSObject或者其他 Objective-C 類的 Swift 類,這些類都能與 Objective-C 無縫連接。所有的步驟都有 Swift 編譯器自動完成,如果你從未在 Objective-C 代碼中導入 Swift 類,你也不需要擔心類型適配問題。另外一種情況,如果你的 Swift 類并不來源自 Objectve-C 類而且你希望能在 Objecive-C 的代碼中使用它,你可以使用下面描述的 @objc 屬性。

@objc可以讓你的 Swift API 在 Objective-C 中使用。換句話說,你可以通過在任何 Swift 方法、類、屬性前添加@objc,來使得他們可以在 Objective-C 代碼中使用。如果你的類繼承自 Objective-C,編譯器會自動幫助你完成這一步。編譯器還會在所有的變量、方法、屬性前加 @objc,如果這個類自己前面加上了@objc關鍵字。當你使用@IBOutlet,@IBAction,或者是@NSManaged屬性時,@objc也會自動加在前面。這個關鍵字也可以用在 Objetive-C 中的 target-action 設計模式中,例如,NSTimer或者UIButton。

當你在 Objective-C 中使用 Swift API,編譯器基本對語句做直接的翻譯。例如,Swift API func playSong(name: String)會被解釋為- (void)playSong:(NSString *)name。然而,有一個例外:當在 Objective-C 中使用 Swift 的初始化函數,編譯器會在方法前添加“initWith”并且將原初始化函數的第一個參數首字母大寫。例如,這個 Swift 初始化函數init (songName: String, artist: String將被翻譯為- (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist 。

Swift 同時也提供了一個@objc關鍵字的變體,通過它你可以自定義在 Objectiv-C 中轉換的函數名。例如,如果你的 Swift 類的名字包含 Objecytive-C 中不支持的字符,你就可以為 Objective-C 提供一個可供替代的名字。如果你給 Swift 函數提供一個 Objecytive-C 名字,要記得為帶參數的函數添加(:)

復制代碼代碼如下:

//Swift
@objc(Squirrel)
class Белка {
    @objc(initWithName:)
    init (имя: String) { /*...*/ }
    @objc(hideNuts:inTree:)
    func прячьОрехи(Int, вДереве: Дерево) { /*...*/ }
}

 

當你在 Swift 類中使用@objc(<#name#>)關鍵字,這個類可以不需要命名空間即可在 Objective-C 中使用。這個關鍵字在你遷徙 Objecive-C 代碼到 Swift 時同樣也非常有用。由于歸檔過的對象存貯了類的名字,你應該使用@objc(<#name#>)來聲明與舊的歸檔過的類相同的名字,這樣舊的類才能被新的 Swift 類解檔。

Objective-C 選擇器(Selectors)

一個 Objective-C 選擇器類型指向一個 Objective-C 的方法名。在 Swift 時代,Objective-C 的選擇器被Selector結構體替代。你可以通過字符串創建一個選擇器,比如let mySelector: Selector = "tappedButton:"。因為字符串能夠自動轉換為選擇器,所以你可以把字符串直接傳遞給接受選擇器的方法。

復制代碼代碼如下:

//Swift
import UIKit
class MyViewController: UIViewController {
    let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))

 

    init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
        super.init(nibName: nibName, bundle: nibBundle)
        myButton.targetForAction("tappedButton:", withSender: self)
    }

    func tappedButton(sender: UIButton!) {
        println("tapped button")
    }
}

 

注意: performSelector:方法和相關的調用選擇器的方法沒有導入到 Swift 中因為它們是不安全的。

如果你的 Swift 類繼承自 Objective-C 的類,你的所有方法都可以用作 Objective-C 的選擇器。另外,如果你的 Swift 類不是繼承自 Objective-C,如果你想要當選擇器來使用你就需要在前面添加@objc關鍵字,詳情請看Swift 類型兼容性。



注:相關教程知識閱讀請移步到swift教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩精品在线播放| 欧美黑人巨大精品一区二区| 日本精品免费观看| 国产精品扒开腿做爽爽爽视频| 国产精品视频1区| 日韩av成人在线观看| 国产成人亚洲精品| 日韩美女写真福利在线观看| 91色中文字幕| 国产亚洲人成网站在线观看| 久久综合国产精品台湾中文娱乐网| 国产精品久久久久久婷婷天堂| 亚洲图片欧洲图片av| 日韩亚洲第一页| 久久久久久伊人| 成人欧美一区二区三区黑人| 色噜噜国产精品视频一区二区| 国产91精品高潮白浆喷水| 国产精品一区二区在线| 国产成人拍精品视频午夜网站| 国产精品扒开腿爽爽爽视频| 欧美成人精品在线视频| 精品免费在线视频| 成人中文字幕在线观看| 91亚洲永久免费精品| 久久99国产综合精品女同| 69av成年福利视频| 精品中文字幕在线2019| 亚洲精品影视在线观看| 欧美激情一区二区三区成人| 国产精品视频内| 精品亚洲一区二区三区在线播放| 久久国产精品影视| www.国产一区| 北条麻妃99精品青青久久| 精品香蕉在线观看视频一| 美日韩精品免费视频| 日韩三级影视基地| 91免费看片在线| 韩国19禁主播vip福利视频| 97久久国产精品| 欧美激情精品久久久久久免费印度| 欧美成人免费全部| 欧美成人小视频| 精品偷拍各种wc美女嘘嘘| 久久久国产一区| 伊人久久久久久久久久久久久| 国产精品久久久久久久久久久不卡| 中文字幕日韩欧美在线视频| 欧美激情一区二区久久久| 国产拍精品一二三| 久久精品中文字幕免费mv| 亚洲级视频在线观看免费1级| 亚洲精品福利资源站| 欧美大片欧美激情性色a∨久久| 国产精品电影久久久久电影网| 国产精品高潮呻吟久久av黑人| 国产日韩在线播放| 午夜精品一区二区三区视频免费看| 国产丝袜视频一区| 成人妇女免费播放久久久| 欧美黑人巨大xxx极品| 欧美与黑人午夜性猛交久久久| 国产成人精品在线视频| 欧美亚洲视频在线看网址| 亚州成人av在线| 欧美日韩国产中文精品字幕自在自线| 久久全国免费视频| 日韩欧美视频一区二区三区| 日韩国产高清污视频在线观看| 97在线视频观看| 欧美性猛交xxxx乱大交极品| 九色精品美女在线| 亚洲精品suv精品一区二区| 亚洲欧美第一页| 国产精品影院在线观看| 久久久久久国产精品| 中文精品99久久国产香蕉| 日韩经典中文字幕| 尤物九九久久国产精品的特点| 亚洲www在线观看| 亚洲偷熟乱区亚洲香蕉av| 欧美做受高潮1| 2020国产精品视频| 欧美一区二区影院| 久久久av免费| 欧美成人网在线| 91tv亚洲精品香蕉国产一区7ujn| 久久99精品久久久久久琪琪| 一本大道香蕉久在线播放29| 最近2019免费中文字幕视频三| 亚洲精品第一国产综合精品| 欧洲成人性视频| 92裸体在线视频网站| 欧美在线影院在线视频| 高清欧美一区二区三区| 欧美精品18videos性欧| 97av在线视频免费播放| 亚洲精品福利在线| 成人福利在线观看| 亚洲一区二区久久久久久| 亚洲精品久久7777777| 久久国产精品视频| 另类色图亚洲色图| 日韩成人小视频| 欧美黑人又粗大| 亚洲高清免费观看高清完整版| 国产精品综合久久久| 日韩欧美国产网站| 成人午夜在线影院| 亚洲综合日韩中文字幕v在线| 日韩成人网免费视频| 色噜噜狠狠狠综合曰曰曰| 国产精品免费久久久久久| 亚洲成人精品av| 综合国产在线视频| 国产日韩中文在线| 国产欧美在线播放| 精品国产91久久久久久老师| 亚洲精品日韩激情在线电影| 国产成人精品免高潮费视频| 亚洲人成在线播放| 青青草国产精品一区二区| yellow中文字幕久久| 成人欧美在线视频| 美女av一区二区三区| 日韩av免费在线观看| 亚洲午夜女主播在线直播| 精品人伦一区二区三区蜜桃免费| 96精品久久久久中文字幕| 国产99久久精品一区二区永久免费| 日本韩国在线不卡| 国产精品人人做人人爽| 亚洲一区美女视频在线观看免费| 国产日韩在线精品av| 色综合色综合网色综合| 亚洲天堂日韩电影| 亚洲国产另类 国产精品国产免费| 久久久噜噜噜久久| 最好看的2019的中文字幕视频| 国产精品免费福利| 久热在线中文字幕色999舞| 91久久精品国产91久久性色| 社区色欧美激情 | 欧美视频中文字幕在线| 欧美影院久久久| 国产99久久精品一区二区永久免费| 欧美怡春院一区二区三区| 亚洲www在线观看| 8050国产精品久久久久久| 永久免费精品影视网站| 欧美视频一区二区三区…| 日本在线观看天堂男亚洲| 欧美高清视频在线| 亚洲韩国日本中文字幕| 亚洲在线视频福利| 日韩中文字幕国产| 国产91精品青草社区| 欧美亚洲日本网站| 日韩av高清不卡| 国产精品久久久久久久久久久不卡| 亚洲第一网站男人都懂| 91精品国产成人www| 亚洲第一页自拍|