程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> Swift挪用Objective-C編寫的API實例

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

編輯:更多關於編程

Swift挪用Objective-C編寫的API實例。本站提示廣大學習愛好者:(Swift挪用Objective-C編寫的API實例)文章只能為提供參考,不一定能成為您想要的結果。以下是Swift挪用Objective-C編寫的API實例正文


互用性是讓 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 類型兼容性。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved