淺談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間的 聯絡
swift句尾不需要分號 ,除非你想在一行中寫三行程式碼就加分號隔開。
swift不要寫main函式 ,程式預設從上往下執行
swift不分.h和.m檔案 ,一個類只有.swift一個檔案
swift不在有地址的概念
swift資料型別都會自動判斷 , 只區分變數var 和常量let
強制轉換格式反過來了 OC強轉:(int)a Swift強轉:int(a)
整數的資料型別可以通過 .min和.max獲得最大和最小值
定義型別的別名語法改變
OC:typedef int MyInt
Swift:typealias MyInt = intswift的模除取餘運算子支援小數了 。 如 5%1.5 = 0.5
關於BOOL型別更加嚴格 ,Swift不再是OC的非0就是真,而是true才是真false才是假
與第10點相聯絡的就是, swift的賦值運算子沒有返回值 。防止誤用“=”和“==”
swift可以多對多賦值 。 let(x,y) = (1,2)
swift的 迴圈語句中必須加{} 就算只有一行程式碼也必須要加
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 就是範圍取3,4,5
a..<b 表示[a,b) 如3,5 就是取範圍3,4
可以直接寫在 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目前是一種開源語言,這意味著谷歌可以將其應用到安卓軟體開發中,同時不改變安卓的開源移動架構。