1. 程式人生 > >淺談Swift和Objective-C之間的那點事。。。

淺談Swift和Objective-C之間的那點事。。。

Swift 是一種新的程式語言,用於編寫 iOS 和 OS X 應用。Swift 結合了 C 和 Objective-C 的優點並且不受C相容性的限制。Swift 採用安全的程式設計模式並添加了很多新特性,這將使程式設計更簡單,更靈活,也更有趣。Swift 是基於成熟而且倍受喜愛得 Cocoa 和 Cocoa Touch 框架,他的降臨將重新定義軟體開發。

Swift 的開發從很久之前就開始了。為了給 Swift 打好基礎,蘋果公司改進了編譯器,偵錯程式和框架結構。我們使用自動引用計數(Automatic Reference Counting, ARC)來簡化記憶體管理。我們在 Foundation 和 Cocoa的基礎上構建框架棧並將其標準化。Objective-C 本身支援塊、集合語法和模組,所以框架可以輕鬆支援現代程式語言技術。正是得益於這些基礎工作,我們現在才能釋出這樣一個用於未來蘋果軟體開發的新語言。

Objective-C 開發者對 Swift 並不會感到陌生。它採用了 Objective-C 的命名引數以及動態物件模型,可以無縫對接到現有的 Cocoa 框架,並且可以相容 Objective-C 程式碼。在此基礎之上,Swift 還有許多新特性並且支援程序式程式設計和麵向物件程式設計。

swfit和OC間的 聯絡

  1. swift句尾不需要分號 ,除非你想在一行中寫三行程式碼就加分號隔開。

  2. swift不要寫main函式 ,程式預設從上往下執行

  3. swift不分.h和.m檔案 ,一個類只有.swift一個檔案

  4. swift不在有地址的概念

  5. swift資料型別都會自動判斷 , 只區分變數var 和常量let

  6. 強制轉換格式反過來了 OC強轉:(int)a Swift強轉:int(a)

  7. 整數的資料型別可以通過 .min和.max獲得最大和最小值

  8. 定義型別的別名語法改變
    OC:typedef int MyInt
    Swift:typealias MyInt = int

  9. swift的模除取餘運算子支援小數了 。 如 5%1.5 = 0.5

  10. 關於BOOL型別更加嚴格 ,Swift不再是OC的非0就是真,而是true才是真false才是假

  11. 與第10點相聯絡的就是, swift的賦值運算子沒有返回值 。防止誤用“=”和“==”

  12. swift可以多對多賦值 。 let(x,y) = (1,2)

  13. swift的 迴圈語句中必須加{} 就算只有一行程式碼也必須要加

  14. swift的switch語句後面以前只能跟整數, 現在可以跟各種資料型別了 ,如浮點字串都行,並且裡面不用寫break,如果不想要沒break的效果 即後面的都想執行 那就寫上關鍵字 fallthrough(注意:在fallthrough後面就不能再定義常量變量了)

1、初始化UIView的子類
在iOS應用上實現UI就需要子類化UIView,也就是要重寫UIView的init方法。注意:兩種語言有所區別。
Objective-C只需在UIView子類中重寫必要的init方法。要初始化一個UIView框架,就要重寫initWithFrame:框架,如下所示:

@implementation SubUIView
- (id) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self != nil) {
        // ...
    }
    return self;
}
@end

然而Swift需要多一些步驟來重寫同一個init方法。首先,重寫使用CGRect框架作為其引數的init方法。根據UIView文件,用Swift語言構建時,須重寫init( coder: ),但我們不需要這種方法,就用如下程式碼處理。類屬性初始化所需的程式碼可以在init( frame: )中執行。

class SubUIView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        // ...
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

2、初始化UIViewController的子類
子類化UIViewController是iOS開發的重要步驟。使用Interface Builder的開發者需要重寫initWithNibName:bundle:,但既然我們用程式碼來構建UI,就不需要執行這一方法了。只需重寫init方法,在其中初始化類屬性即可。

@implementation SubUIViewController
- (id) init
{
    self = [super init];
    if (self != nil) {
        // ...
    }
    return self;
}
@end

Swift也一樣要重寫init()方法。實現指定的初始化init(nibName:bundle: )來子類化UIViewController。重申:此過程不適用Interface Builder,所以無需定義nibName和bundle的值,而是呼叫比指定初始化更簡單的convenience初始化,將指定初始化init(nibName:bundle: )設為零。現在呼叫init()來初始化類,用重寫的(nibName:bundle: )執行類屬性。

class SubUIViewController: UIViewController {
    convenience init() {
        self.init(nibName: nil, bundle: nil)
    }
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Initialize properties of class
    }  
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
//現在可以建立和呼叫UIViewController的子類
let viewController: SubUIViewController = SubUIViewController()
self.navigationController?.pushViewController(viewController, animated: false)

3、使用Auto Layout來實現View
沒有Interface Builder的情況下,就用Auto Layout中的NSLayoutConstraint類來設定View的大小和位置——注意Objective-C和Swift在這裡有微妙差別。

Objective-C使用NSLayoutConstraint類中的constraintWithItem方法。

+ (instancetype)constraintWithItem:(id)view1
                         attribute:(NSLayoutAttribute)attr1
                         relatedBy:(NSLayoutRelation)relation
                            toItem:(id)view2
                         attribute:(NSLayoutAttribute)attr2
                        multiplier:(CGFloat)multiplier
                          constant:(CGFloat)c

Swift使用同一個類中的init方法。

convenience init(item view1: AnyObject,
       attribute attr1: NSLayoutAttribute,
       relatedBy relation: NSLayoutRelation,
          toItem view2: AnyObject?,
       attribute attr2: NSLayoutAttribute,
      multiplier multiplier: CGFloat,
        constant c: CGFloat)

如果是Objective-C,則執行以下程式碼。這段程式碼將建立NSLayoutConstraint(定義self.profileImageView和self之間的位置),然後新增到self上。

[self addConstraint:[NSLayoutConstraint constraintWithItem:self.profileImageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:kMessageCellLeftMargin]];

使用Swift也可以建立NSLayoutConstraint:

self.addConstraint(NSLayoutConstraint.init(item: self.profileImageView!, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: kMessageCellLeftMargin))

4、選擇器
使用UIButton、NSNotificationCenter、NSTimer等時,使用選擇器來分配要執行的方法。在Objective-C中,@selector指令代表使用選擇器。

- (void)test
{
    // ...
    mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerCallback:) userInfo:nil repeats:YES];
}

- (void)timerCallback:(NSTimer *)timer
{
    // ...
}

Swift中,不需要使用指令或字串來分配方法。

func test() {
    // ...
    self.mTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerCallback:", userInfo: nil, repeats: true)
    // ...
}

func timerCallback(timer: NSTimer) {
    // ...
}

5、字串
儘管在Swift程式碼中也可以用Objective-C專門處理字串的NSString,但要使用以String物件為屬性的UITextField上的文字或其他的話,就要清楚NSString和String的區別。

在Objective-C中,UITextField上的文字為NSString,所以屬性的長度就是字串的長度。

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    NSString *message = [textField text];
    if ([message length] > 0) {
        // ...
    }

    return YES;
}

Swift是沒有長度屬性的,所以要用characters屬性的count屬性。

func textFieldShouldReturn(textField: UITextField) -> Bool {
    let message: String = textField.text!
    if message.characters.count > 0 {
        // ...
    }

    return true
}

在Objective-C中,我們用stringWithFormat:來建立一個格式化字串。

[self.typingLabel setText:[NSString stringWithFormat:@"%d Typing something cool....", count]];

在Swift中,String裡沒有stringWithFormat方法,所以用init(format:_ arguments: )代之。我們可以分配一個與NSString格式化結構相同的格式化字串來建立一個新字串,然後給arguments賦以相關的值;

self.typingLabel?.text = String.init(format: "%d Typing something cool...", count)

6、從資料型別得到最小&最大值
從數字格式上得到最小和最大值而言,Objective-C和Swift也有差別。Objective-C使用一個預定義巨集來得到最小和最大值,但Swift則可以直接從資料型別上得到這些值。Objective-C使用的是如下的巨集:

CGFLOAT_MAX
CGFLOAT_MIN
INT32_MAX
INT32_MIN
LLONG_MAX
LLONG_MIN

而Swift則從資料型別上得到最小和最大值

CGFloat.max
CGFloat.min
Int32.max
Int32.min
Int64.max
Int64.min

7、字典和列舉值
Objective-C用NSDictionary來定義NSAttributedString的屬性。Swift則用Dictionary而不是NSDictionary,但想為Dictionary分配列舉值的時候,做法稍有不同。

Objective-C直接為NSDictionary分配鍵值,如下所示:稱為NSUnderlineStyleSingle的列舉值不能作為NSDictionary值直接分配,所以要先用@()將它轉換成一個物件。

NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};

Swift可以直接為Dictionary分配鍵值(如下所示)。如果該值定義為AnyObject,那麼Swift就跟Objective-C一樣不能直接使用列舉值,而是使用rawValue屬性代之。

let underlineAttribute: [String: AnyObject] = [NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue]

8、swift獨有的範圍運算子

a...b 表示 [a,b]  如3...5  就是範圍取345

a..<b 表示[a,b)  如35 就是取範圍34

可以直接寫在 for-in 迴圈中,或者if判斷中 如  for x in 0...5 {}

9 、swift獨有的溢位運算子
當你往一個整型常量或變數賦於一個它不能承載的大數時,Swift不會讓你這麼幹的,它會報錯。這樣,在操作過大或過小的數的時候就很安全了。

var potentialOverflow = Int16.max
// potentialOverflow 等於 32767, 這是 Int16 能承載的最大整數
potentialOverflow += 1
//  出錯了
//當然,你有意在溢位時對有效位進行截斷,你可採用溢位運算,而非錯誤處理。Swfit為整型計算提供了5個&符號開頭的溢位運算子。
//    &+,&-,&*,&/,&%
var willOverflow = UInt8.max
// willOverflow 等於UInt8的最大整數 255
willOverflow = willOverflow &+ 1
// 這時候 willOverflow 等於 0

10 、 swift獨有的元組型別
var point = (x:15,y:20.2)

就是元組名是 point ,裡面有兩個元素x和y。 有點類似於結構體但是不是

想取出裡面的x的值賦值就是 point.x = 30 或者point.0 = 30 (注:元組裡面的許多元素可以看作有陣列的下標)

可以省略內部元素的名稱 var point = (15,20.2) 但是這樣的話,想取出值就只能用point.0 = 30 這一種方法了,因為人家沒有元素名了好吧。

也可以明確指定元組內每一個元素的型別,假如那個20.2我不想要double型別 我想要是float型別。可以 var point = (Int,String) = (15,20.2)

注意:元組名稱和型別不能共存 ,比如你指定型別了 後面就不可以再指定名稱了 var point = (Int,String) = (x:15,y:20.2)

如果你想列印的話就寫println(point) 打印出來就是(10,20.2)

並且在初始化的時候也可以用下劃線省略不需要的元素 如 var point = (_ ,20.2);

11、在switch語句中使用元組型別時還可以用類似SQL語句的語法 新增過濾條件

switch point{

  case let(x,y) where x== y:

      println("x與y的值相等");



}

12、函式的外部引數名

  • 函式原來的格式是這樣(箭頭後面是返回值) func Sum (num1:Int,num2:Int) –>Int{}

  • 呼叫時是 Sum(20,20)

  • 加外部引數名的話在方法呼叫時可讀性更好,是寫在原引數名的前面, 呼叫時也必須書寫

  • 即 func Sum(numone num1:Int,numtwo num2:Int) –>Int{}

  • 呼叫時寫 Sum(numone:20,numbertwo:20)

  • 如果覺得這樣有點麻煩,可以讓外部引數名和內部引數名一樣

  • 就是 func Sum (#num1:Int,#num2:Int) –>Int{}

  • 呼叫時寫 Sum(num1:20,num2:20)

13、函式的預設引數值

func addStudent (name:string,age:Int = 20) –>string{}

設定了預設的年齡為20 所以再呼叫時只需要寫個名字

addStudent(“ZTE”)

要注意的是,使用了預設引數值, 系統會自動生成一個外部引數名。

想改名字也就要寫外部引數名了 即 addStudent(“ZTE”,age:18)

14、函式的輸入輸出引數

在函式宣告時就用inout代替var 這樣以後可以在函式內部修改外面的值 類似於C語言的傳入指標

func change (inout num:Int) {
  num = 10
}
var a = 20
change(&a)

得到的結果就是10

(注意:寫了輸入輸出引數就不能再用預設函式值的語法了)

用輸入輸出引數,實現多個返回值功能

func SumAndMinus(num1:Int,num2:Int,inout sum:Int,inout minus:Int){
  sum = num1 + num2
  minus = num1 - num2
}
var sum = 0 ,minus =0
SumAndMinus(20,5,∑,−)

PS:谷歌醞釀將蘋果Swift作為安卓APP主要開發語言

安卓作業系統的軟體開發語言是Java,而在過去幾年中,有關Java的版權,谷歌(微博)和甲骨文之間發生了長期的訴訟。最新外媒訊息稱,谷歌正在考慮將蘋果開發的Swift作為未來安卓軟體開發的“一級”語言,此外Facebook、Uber等公司也開始越來越重視Swift的使用。

據美國科技新聞網站TheNextWeb引述知情人士報道,此前蘋果Swift轉變為開放原始碼語言,而谷歌、Facebook、和Uber三家公司的代表曾經在英國倫敦開會,專門討論Swift語言,谷歌決定逐步在安卓系統中採用這種語言。

Java目前是安卓開發最為重要的語言。訊息人士表示,至少在最初階段,Swift語言不會取代Java的重要地位。目前谷歌和甲骨文之間有關Java的訴訟仍在持續中,引發了外界隱憂,訊息人士稱,谷歌認為Swift和Java相比有著廣泛的優勢。

Swift目前是一種開源語言,這意味著谷歌可以將其應用到安卓軟體開發中,同時不改變安卓的開源移動架構。