Apple Swift或将吸引.NET开发者转向iOS开发
Apple Swift或将吸引.NET开发者转向iOS开发
引言
在今年的全球开发者大会上,苹果公司宣布了其未来的iOS和Mac OSX开发语言——Swift。这对于关注苹果的任何人来说都是一个巨大的惊喜。经过四年的开发,苹果公司创造并公布了将成为OS X和iOS新一代应用程序基础的技术。Swift的设计原则包括安全性、现代化的语法和强大的功能。深入了解这门新语言,我惊讶地发现Swift的编写方式与我们实现C#的方式相似。我想通过对比Swift和C#的新特性,为使用C#的开发者提供一个概览,帮助他们快速理解Swift语言的优势。
背景
许多开发者一直梦想着创建iOS应用程序,但入门Objective-C语言并不容易。但现在,得益于Swift,这个问题或许可以得到解决。Swift中的许多概念都源自我们之前接触过的现代化语言。
Swift与C#极为相似
变量和常量
Swift提供的第一个重要特性是类型推断,因此类型声明不再是强制性的。编译器可以通过评估变量的赋值来检测类型。微软在.NET 3.0中添加了此功能,并且它已基本普及。
Swift | C#, F# |
var quantity = 10
var price : Double = 1500.99
let tax = 2.99 // constant
|
var quantity = 10;
double price = 1500.99;
const double tax = 2.99
let tax = 2.99 // F# language
|
在Swift中,我们可以看到的一点是,每条语句末尾不再需要分号。Swift语言常量使用 `let` 关键字声明,变量使用 `var` 关键字声明。在C#语言中,变量也使用 `var` 关键字声明,而在F#中,`let` 关键字用于声明一个值。当变量未立即赋值时,需要显式指定变量的类型。
Swift | C# |
errCode: String
|
string errCode;
|
Swift引入了新的可选类型。可选类型允许我们指示一个变量可能有一个值,也可能为null。Swift的可选类型提供编译时检查,可以防止一些在运行时发生的常见编程错误。一旦我们知道可选类型包含一个值,我们就可以通过在其名称后添加感叹号 (!) 来解包可选类型。这被称为强制解包。这类似于在C#中声明可空变量。
Swift | C# |
var findNumber: Int? // Null value
if (findNumber != nil )
{ var searchValue = findNumber! }
|
int? findNumber;
if (findNumber.HasValue)
{ var searchValue = findNumber.Value; }
|
诸如将字符串转换为大写或小写,判断此字符串实例的开头/结尾是否匹配指定字符串等 `String` 方法,都非常相似。
Swift | C# |
var strName = "iPhone 6"
if strName.uppercaseString.hasPrefix("IP")
{ // to do }
if strName.lowercaseString.hasSuffix("6")
{ // to do }
|
var strName = "iPhone 6";
if (strName.ToUpper().StartsWith("IP"))
{ //to do }
if (strName.ToLower().EndsWith("6"))
{ //to do }
|
Swift的另一个我喜欢的特性是 `string` 模板,可以使用变量、常量以及表达式的结果来构建字符串,只需将它们放在“`\()`”中即可。C#可以通过使用 `string` 格式化来实现相同的功能。
Swift | C# |
var total = "Total: \(price * Double(quantity))"
|
var total = String.Format
("Total {0}", price * quantity);
|
数组
Swift中声明数组的语法与C#略有不同,但功能非常相似。有些函数实现了相同的功能。我们可以逐行对照下面的示例进行理解。
Swift | C# |
var arrayItem: [String] = ["iPhone","iPad"]
// for-in loop
for item in arrayItem { // to do }
// check empty
if arrayItem.isEmpty { // to do }
// Get item by index
var first = arrayItem[0]
// Set item by index
arrayItem[0] = "Macbook"
// remove item
arrayItem.removeAtIndex(0)
|
var arrayItem = new string[] { "iPhone", "iPad" };
// for-each loop
foreach (var item in arrayItem) { // to do }
// check empty
if (arrayItem.Length == 0) { // to do }
// Get item at index
var first = arrayItem[0]
// Set item by index
arrayItem[0] = " Macbook "
// remove item
var list = arr.ToList();
list.RemoveAt(0);
|
与变量一样,数组默认是强类型的,从这个角度看,Swift与JavaScript基本相同。
Swift | C# |
var arrayItem = ["iPhone","iPad"]
|
var arrayItem = ["iPhone","iPad"];
|
在我看来,Swift中的数组与C#中的 `List` 极为相似。
词典
C#和Swift在声明和迭代方面有非常相似的方法,但存在细微差别,不过这似乎是小事。下表展示了Swift和C#中字典的功能对比。
Swift | C# |
var listItem: Dictionary<int, string=""> =
[1: "iPhone", 2: "iPad"]
// Iterate dictionary
for (key, value) in listItem
{ // todo key and value }
// set item to dictionary
listItem[3] = "Macbook"
// Remove item out dictionary by key
listItem.removeValueForKey(2)
// Get item from dictionary by key
var first = listItem[1]
|
var listItem = new Dictionary<int, string>()
{{1, "iPhone"}, {2, "iPad"}};
// Iterate dictionary
foreach (var item in listItem)
{ // todo item.key and item.value }
// set item to dictionary
listItem[3]="Macbook";
// Remove item out dictionary by key
listItem.Remove(2);
// Get item from dictionary by key
var first = listItem[1];
|
我们可以通过赋值为null来移除Swift中的一个元素(`Listitem[2]= nil`),这看起来像JavaScript的编码风格。
If 条件
Swift不需要在匹配条件周围加上括号“`()`”。括号是可选的,但重要的是,`if` 语句必须用大括号“`{}`”括起来,即使代码只执行一行。在C#中,如果`if`语句只执行一行代码,则不需要使用大括号。原因是苹果希望Swift成为一种安全的语言,可以防止一些意外的bug,例如苹果之前遇到的SSL“goto fail”问题。
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail; /* MISTAKE! THIS LINE SHOULD NOT BE HERE */
“goto fail”被调用了两次。这个bug似乎很可能是开发者在复制粘贴时造成的,但一个小小的代码问题可能导致灾难性的后果。下面的示例比较了Swift和C#中的`if`条件。
Swift | C# |
if searchItem == "iPhone" // don't need ()
{ vat = 1.99 } // must have {}
else if searchItem == "iPad"
{ //todo }
else
{ //todo }
|
if (searchItem == "iPhone")
vat = 1.99 ; // Don’t need {}
else if (searchItem == "iPad")
{ //todo }
else
{ //todo }
|
Switch 语句
Swift中的 `Switch` 语句也与C#的语法非常相似。但在Swift中,“`break`”语句不是必需的,并且default子句是强制性的。
Swift | C# |
switch index {
case 0: // to do
case 1: // to do
default: // it is mandatory.
}
|
switch (index) {
case 0: break ;// to do
case 1: break ;// to do
default: break;
}
|
Swift在 `Switch` 语句中支持 `Case` 语句中的范围,在这方面Swift似乎比C#更简单。
Swift | C# |
switch index {
case 0, 1: // multiple value
case 2...10: // multiple value
default: // todo }
|
switch (index) {
case 0:
case 1:
break; // todo
default: break; }
|
for – while – do … while
Swift提供了非常接近C#语法的基本 `for`、`while` 和 `do`-`while` 循环。幸运的是,语法上没有显著变化。唯一的区别是Swift的条件部分不需要括号。
Swift | C# |
// For loop
for var i = 0 ; i < 100 ; ++i { // to do }
// while
while !done { // to do }
// do .. while
do { // to do } while !done
// for in range
for index in 1...5 { // to do }
|
// For loop
for(var i = 0; i < 100; i++) { // to do }
// while
while !done { // todo }
// do .. while
do { // todo } while !done
// for in range
foreach (var i in Enumerable.Range(1, 5))
{ // to do }
|
函数
与C#一样,函数在Apple Swift中也是一等公民。这意味着它可以被存储在变量或常量中,作为参数传递,赋值给某个值,或者作为另一个函数的返回值。基本上,C#和Swift之间没有太多区别。
Swift | C# |
func Total(quantity: Int, price: Double) -> Double {
return Double(quantity) * price }
// Multiple return values
func getDetail() ->
(name:String,quantity: Int, price :Double)
{ return ("iPhone6",2, 1500.99) }
// in Out parameter
func swapNumbers(inout a: Int, inout b: Int)
{ var c = a; a = b; b = c; }
// Function Type
var result : (Int, Double) -> Double = Total
//or
var result -> Double = Total
|
double Total(int quantity, double price)
{ return quantity * price; }
// Multiple return values
Tuple<string, int, double> getDetail()
{ return new Tuple<string,int ,
double>("iPhone6", 2, 1500.99); }
// in Out parameter
void swapNumbers (ref int a, ref int b)
{ var c = a; a = b; b = c; }
// Function Type
Func<int, double, double> result = Total;
|
由于Swift和C#都支持将函数作为参数传递、将函数作为返回类型等,我们可以看到它们的基本语法非常相似。正如你在上面的比较中所见,这两种语言之间没有太多差异。
协议
在C#中,我们已经使用过接口,而Swift中的Protocols(协议)看起来就像接口。协议是一组方法和属性,它们本身不实现任何东西;它只是定义了所需的属性和方法。任何使用该协议的类都必须实现协议中规定的方法和属性。协议的重要作用是实现类之间的低耦合。
Swift | C# |
protocol Purchase
{
var name : String { get set};
var quantity : Int { get set};
var price : Double { get set};
func Total() -> Double;
}
|
interface Purchase
{
string name { get; set;}
int quantity { get; set;}
double price { get; set;}
double total();
}
|
类
下表展示了如何在C#和Swift中创建类。
Swift | C# |
class ItemDetail {
var itemName : String
var itemQuantity : Int
var itemPrice : Double
init(name: String, quantity: Int, price:Double)
{
self.itemName = name;
self.itemQuantity = quantity;
self.itemPrice = price;
}
func Total () -> Double {
return itemPrice * Double(itemQuantity)
}
}
// Access class
var itemDetail =
ItemDetail (name:"iPhone",
quantity: 2, price: 100.99)
|
public class ItemDetail {
private string itemName;
private int itemQuantity;
private double itemPrice;
public ItemDetail
(string name, int quantity,
double price) {
itemName = name;
itemQuantity = quantity;
itemPrice = price;
}
public double Total () {
return itemPrice * itemQuantity;
}
}
// Access class
ItemDetail iTemDetail =
new ItemDetail ("phone", 1, 1.2);
|
Swift和C#定义属性、函数和类构造函数的方式看起来没有区别。这只是语法上的一些小改动,没有大的差异。C#开发者可以快速学会。两者都支持子类,但我更想展示Swift类如何遵循协议并实现协议中的属性和函数。
class iPhone : Purchase {
var name = "iPhone"
var quantity = 1
var price = 1500.99
func Total () -> Double {
return price * Double(quantity)
}
}
这与我们在C#中实现继承自接口的类的方式相同。
扩展
Swift的一个强大特性是扩展,它允许为现有的结构(如类、结构体或枚举)添加新功能。实现扩展的方式也非常类似于C#。下面的演示展示了如何通过添加 `Max`、`Min` 和 `Average` 等函数来扩展Swift和C#的数组。
Swift | C# |
extension Array {
var Min: T { // to do }
var Max: T { // to do }
var Average: T { // to do }
}
// call extension
var max = arrayNumber.Max
|
public static class ArrayExtension
public static T Max<T>(T[] arr) { // to do }
public static T Min<T>(T[] arr) { // to do }
public static T Average<T>(T[] arr) { // to do }
}
// call extension
var max = ArrayExtension.Max(arr);
|
闭包
闭包用于将函数及其上下文打包成一个对象。这使得代码更容易调试和阅读。下面的代码展示了如何使用闭包对数据进行排序。
Swift | C# |
var arrayNumber = [4,5,3]
var list = sorted(arrayNumber, { s1, s2 in
return s1 < s2 })
|
List<int> list = new List<int> { 4, 5, 3, };
list.Sort((x, y) => Convert.ToInt32((x < y)));
|
总的来说,如果我们习惯于使用C#,那么编写Swift代码并不难。
闭包可以有效地用更少的代码和更具表现力的实现来表达开发者的意图。就像我们在C#中使用闭包一样,理解和使用闭包是提高iOS开发效率的重要因素。
Generic
泛型是编写强类型且灵活代码的强大方式。Swift构建了与C#语言相同的泛型概念。使用泛型,开发者可以实现一个函数,该函数适用于所有类型的对象。下面数组/列表中的搜索项函数展示了简单的泛型实现。
Swift | C# |
func indexArray<T :Equatable>
(item :T, array :[T]) -> T?
{
for value in array
{
if(value == item)
{
return value
}
}
return nil
}
|
public static Nullable<T>
IndexList<T>(T item, T[] arr) where T : struct
{
foreach (var i in arr)
if (i.Equals(item))
{
return i;
}
return null;
}
|
实际上,代码表明我们可以像处理C#一样开发Swift应用程序。这只是一些小的语法变化。
关注点
Swift和C#之间存在许多相似之处。我们在使用Swift开发iOS应用程序时,可以利用我们现有的技能和知识。最重要的是,Swift的新语法现在更容易上手,特别是对于那些拥有.NET背景的开发者。
Swift并非最终产品,苹果仍在不断完善Swift。看起来未来几个月内会添加新功能。熟悉Swift语言是值得的。
历史
- 2014年12月5日:初始版本