Swift已经推出了一段时间了,今天来总结一下Swift与Objective-c(以下简称OC)的语法有哪些不同。
1.常量与变量:
在Swift中定义常量和变量很简单,常量使用let关键字,变量使用var关键字。
var numberOfRows = 30
let maxNumberOfRows = 100
const int count = 10;
double price = 23.55;
NSString *myMessage = @"Objective-C is not dead yet!";
let count = 10
// count会被识别为Int
var price = 23.55
// price会被识别为Double
var myMessage = "Swift is the future!"
// myMessage会被识别为String
var myMessage : String = "Swift is the future!"
在OC中你需要在每一句的后面写上“;”以表达结束,不然会报错,在Swift中你不需要再写分号了,当然你写上也没有问题。
var myMessage = "No semicolon is needed"
3.String
在Swift中字符串的类型是String,不论你定义的是常量字符串还是变量字符串。
let dontModifyMe = "You cannot modify this string"
var modifyMe = "You can modify this string"
在Swift中连接两个字符串组成新字符串非常方便,使用“+”:
let firstMessage = "Swift is awesome. "
let secondMessage= "What do you think?"
var message = firstMessage + secondMessage
println(message)
在OC中我们使用stringWithFormat方法:
NSString *firstMessage = @"Swift is awesome. ";
NSString *secondMessage = @"What do you think?";
NSString *message = [NSString stringWithFormat:@"%@%@", firstMessage, secondMessage];
NSLog(@"%@", message);
var string1 = "Hello"
var string2 = "Hello"<pre name="code" class="plain">if string1 == string2 {
println("Both are the same")
}
数组的用法Swift和OC差不多,我们来看示例:
在OC中:
NSArray *recipes = @[@"Egg Benedict", @"Mushroom Risotto", @"Full Breakfast", @"Hamburger",
@"Ham and Egg Sandwich"];
var recipes = ["Egg Benedict", "Mushroom Risotto", "Full Breakfast", "Hamburger", "Ham and Egg
Sandwich"]
和NSArray相似,Swift中的Array也有很多方法,比如count方法返回数组中的元素个数:
var recipes : [String] = ["Egg Benedict", "Mushroom Risotto", "Full Breakfast", "Hamburger",
"Ham and Egg Sandwich"]<pre name="code" class="plain">var numberOfItems = recipes.count
// recipes.count will return 5
recipes += ["Thai Shrimp Cake"]
不过请注意这个方法是数组间的,如果一个单个元素要加入数组中请在元素外面增加[]。
要取出或者替换数组中的元素,使用索引,这点跟OC中相同:
var recipeItem = recipes[0]
recipes[1] = "Cupcake"
recipes[1...3] = ["Cheese Cake", "Greek Salad", "Braised Beef Cheeks"]
这里替换的是recipes中的第二到第四个元素。
5.Dictionary字典
字典是一种集合类型,由键值对组成,这一点和OC中的NSDictionary很类似,请看示例:
OC中:
NSDictionary *companies = @{@"AAPL" : @"Apple Inc", @"GOOG" : @"Google Inc", @"AMZN" :
@"Amazon.com, Inc", @"FB" : @"Facebook Inc"};
var companies = ["AAPL" : "Apple Inc", "GOOG" : "Google Inc", "AMZN" : "Amazon.com, Inc",
"FB" : "Facebook Inc"]
你也可以声明它的字典类型:
var companies: Dictionary<String, String> = ["AAPL" : "Apple Inc", "GOOG" : "Google Inc",
"AMZN" : "Amazon.com, Inc", "FB" : "Facebook Inc"]
for (stockCode, name) in companies {
println("\(stockCode) = \(name)")
}
for stockCode in companies.keys {
println("Stock code = \(stockCode)")
}
for name in companies.values {
println("Company name = \(name)")
}
companies["TWTR"] = "Twitter Inc"
在OC中创建类的话,会得到两个文件,一个接口文件(.h文件)和一个实现文件(.m文件)。
而在Swift中生成类只有一个文件.swift文件。
示例:
class Recipe {
var name: String = ""
var duration: Int = 10
var ingredients: [String] = ["egg"]
}
class Recipe {
var name: String?
var duration: Int = 10
var ingredients: [String]?
}
这样当你创建一个类的实例的时候:
var recipeItem = Recipe()
recipeItem.name = "Mushroom Risotto"
recipeItem.duration = 30
recipeItem.ingredients = ["1 tbsp dried porcini mushrooms", "2 tbsp olive oil", "1 onion,
chopped", "2 garlic cloves", "350g/12oz arborio rice", "1.2 litres/2 pints hot vegetable
stock", "salt and pepper", "25g/1oz butter"]
OC中:
@interface SimpleTableViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
class SimpleTableViewController : UIViewController, UITableViewDelegate, UITableViewDataSource
Swift允许你在类、结构体和枚举中创建方法。
下面是一个没有参数和返回值的方法:
class TodoManager {
func printWelcomeMessage() {
println("Welcome to My ToDo List")
}
}
todoManager printWelcomeMessage];
todoManager.printWelcomeMessage()
class TodoManager {
func printWelcomeMessage(name:String) -> Int {
println("Welcome to \(name)'s ToDo List")
return 10 }
}
你可以这样调用上面的方法:
var todoManager = TodoManager()
let numberOfTodoItem = todoManager.printWelcomeMessage("Simon")
println(numberOfTodoItem)
Swift中的控制流和循环颇有C语言的风格。
8.1for循环
for循环使用 for - in的结构,并且可以和Range(...或者..<)配合使用:
for i in 0..<5 {
println("index = \(i)")
}
index = 0
index = 1
index = 2
index = 3
index = 4
如果我们使用...这是个闭集合,结果会返回:
index = 0
index = 1
index = 2
index = 3
index = 4
index = 5
for var i = 0; i < 5; i++ {
println("index = \(i)")
}
8.2 if-else结构
和OC中很像,只不过Swift中更简单一些,条件语句不需要写在括号中:
var bookPrice = 1000;
if bookPrice >= 999 {
println("Hey, the book is expensive")
} else {
println("Okay, I can affort it")
}
Switch中的switch结构拥有非常强大的功能。
示例:
switch recipeName {
case "Egg Benedict":
println("Let's cook!")
case "Mushroom Risotto":
println("Hmm... let me think about it")
case "Hamburger":
println("Love it!")
default:
}
println("Anything else")
另外你可以看到在每个case中我们都没有写break,在OC中你必须在每个case中写break,否则在当前case结束后会进入下一个case,在Swift中当前case被执行后就会自动跳出switch,如果需要进入下一个case,添加fallthrough语句。
最后,switch的case中可以包含Range操作:
var speed = 50
switch speed {
case 0:
println("stop")
case 0...40:
println("slow")
case 41...70:
println("normal")
case 71..<101:
println("fast")
default:
println("not classified yet")
}
元组类型在OC中是没有的,它可以包含多种不同的数据类型,你可以把它用作方法的返回值,这样就可以用一个元组来代替返回一个复杂的对象了。例如:
let company = ("AAPL", "Apple Inc", 93.5)
let (stockCode, companyName, stockPrice) = company
println("stock code = \(stockCode)")
println("company name = \(companyName)")
println("stock price = \(stockPrice)")
let product = (id: "AP234", name: "iPhone 6", price: 599)
println("id = \(product.id)")
println("name = \(product.name)")
println("price = USD\(product.price)")
class Store {
func getProduct(number: Int) -> (id: String, name: String, price: Int) {
var id = "IP435", name = "iMac", price = 1399
switch number {
case 1:
id = "AP234"
name = "iPhone 6"
price = 599
case 2:
id = "PE645"
name = "iPad Air"
price = 499
default:<span style="font-family: Arial, Helvetica, sans-serif;">break }</span><pre name="code" class="plain"> return (id, name, price)
}
}
let store = Store()
let product = store.getProduct(2)
println("id = \(product.id)")
println("name = \(product.name)")
println("price = USD\(product.price)")
10.1可选型
可选型通常用在变量之中,可选型的默认值是nil。如果你给一个非可选型的变量赋值nil会报错:
var message: String = "Swift is awesome!" // OK
message = nil // compile-time error
class Messenger {
var message1: String = "Swift is awesome!" // OK
var message2: String // compile-time error
}
NSString *message = @"Objective-C will never die!";
message = nil;
class Messenger {
NSString *message1 = @"Objective will never die!";
NSString *message2;<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
class Messenger {
var message1: String = "Swift is awesome!" // OK
var message2: String? // OK
}
Swift语言设计的时候有很多安全方面的考虑,可选型表示了Swift是一门类型安全的语言,从上面的例子中你可以看到Swift中的可选型会在编译时就去检查某些可能发生在运行时的错误。
考虑下面的OC中的方法:
- (NSString *)findStockCode:(NSString *)company {
if ([company isEqualToString:@"Apple"]) {
return @"AAPL";
} else if ([company isEqualToString:@"Google"]) {
return @"GOOG";
}
return nil; }
假设我们在类中定义这个方法,并且在类中使用它:
NSString *stockCode = [self findStockCode:@"Facebook"]; // nil is returned<pre name="code" class="plain">NSString *text = @"Stock Code - ";
NSString *message = [text stringByAppendingString:stockCode]; // runtime error
NSLog(@"%@", message);
上面OC中的代码我们在Swift中的话是这样写的:
func findStockCode(company: String) -> String? {
if (company == "Apple") {
return "AAPL"
} else if (company == "Google") {
return "GOOG"
}
return nil }<pre name="code" class="plain">var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
let message = text + stockCode // compile-time error
println(message)
10.3解包可选型
在上面我们已经看到了可选型的用法,那么我们如何判断一个可选型的变量有值还是为nil呢?
示例:
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
if stockCode != nil {
let message = text + stockCode!
println(message)
}
如果我们忘记做空值判断会怎样?你进形了强制拆封所以不会发生编译时错误
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
let message = text + stockCode! // runtime error
Can’t unwrap Optional.None
10.4可选绑定
除了强制拆封,可选绑定是一个更简单更好的做法。你使用if - let结构的可选绑定来判断一个变量是不是空值
示例:
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
if let tempStockCode = stockCode {
let message = text + tempStockCode
println(message)
}
因为tempStockCode是一个新的常量,你不必再使用!来获取它的值。
你可以简化这个过程:
let text = "Stock Code - "
if var stockCode = findStockCode("Apple") {
let message = text + stockCode
println(message)
}
10.5可选链
我们有一个类Code,里面有两个属性code和price,它们的类型是可选型。把上面示例中的stockCode方法的返回值由String改为返回一个Code类型。
class Stock {
var code: String?
var price: Double?
}
func findStockCode(company: String) -> Stock? {
if (company == "Apple") {
let aapl: Stock = Stock()
aapl.code = "AAPL"
aapl.price = 90.32
return aapl
} else if (company == "Google") {
let goog: Stock = Stock()
goog.code = "GOOG"
goog.price = 556.36
return goog }
return nil }
if let stock = findStockCode("Apple") {
if let sharePrice = stock.price {
let totalCost = sharePrice * 100
println(totalCost)
}
}
上面的代码运行没有问题,不用if let我们有更简单的办法,你可以把上面的代码改成可选链的操作,这个特性允许我们把多个可选类型用?连接,做法如下:
if let sharePrice = findStockCode("Apple")?.price {
let totalCost = sharePrice * 100
println(totalCost)
}