Swift语言常见问题

Tags: Swift ios

    Swift是苹果公司为Cocoa开发而设计的全新的、现代的、类型安全的编程语言。Swift已经开发了4年在今年的WWDC大会上正式公布。Swift采用了许多语言优秀的特性,包括Objective-C, Rust, Haskell, Ruby, Python, C#, CLU 等等,Swfit语法更简单、简洁、从而降低进入iOS开发的门槛,使过程更加愉快。在这篇Swift语言FAQ中,我们将回答很多在的论坛、微博、电子邮件和StackOverflow上常见的问题。

基础知识

我是个初学者。我应该学习Objective-C、Swift或两者兼而有之?

    在我们看来,这取决于你是否打算在公司从事iOS工作或作为一个独立开发人员。

    如果在公司作为一个全职的iOS开发人员或顾问工作:如果你学习Swift和Objective-C是最好的。因为许多iOS开发公司都在使用Objective-C,你需要了解现有的代码,而且现在部分企业不一定会转换到Swift。现在有一堆Objective-C的iOS库、教程、示例项目。您同样还需要了解Swift,因为随着时间的推移大部分系统都会过渡到Swift。

    如果你是一个独立开发人员:如果你打算从一开始就使用Swift,你只能仅仅通过Swift解决问题。但是,如果你能抽出时间学习Objective-C中这样你可以利用现有庞大的Objective-C的资源和库。

我是一个有多年Objective-C开发经验的开发者,难道在Swift中我只是个初学者

    是也不是。如果你一直在苹果平台开发你仍然有巨大的优势,因为你已经熟悉Xcode和Cocoa/Cocoa Touch APIs。由于学习的Xcode和数以千计的Cocoa/Cocoa Touch APIs比学习Swift更加耗时,所以一旦你熟悉了Swift代码的编写方式,你肯定会非常快上手。

是否iOS 8 和 OS X Yosemite应用只能用Swift开发?

    不,苹果设计Swift时考虑到需要与Objective-C可以流畅的互操作,反之亦然!苹果并没有完全转换Objective-C的API和框架到Swift,而且你可以在Swift代码中使用Objective-C的API和框架。具体的答案只有时间会告诉我们,但在很长时间内可能大部分iOS和OS X的App将继续依赖于Objective-C的。

Swift是否与其他版本的IOS或OS X兼容?

    是的!Xcode中6可以编译的Swift代码可以部署在iOS7及更高版本和OS X10.9及更高版本。苹果公司的WWDC应用程序就是用Swift开发的,你可以从App Store下载!但是,请记住,苹果不允许将Xcode beta版本编译的应用提交到App Store。因此,您将需要等到Xcode 6的最终版本,才能将你用Swift编写的引用在App Store上线。

Siwft是Objective-C的替代或补充吗?

    引用苹果的官方表述:“Objective-C是不会消失的,无论是Swift或Objective-C都是Cocoa and Cocoa Touch开发的一等公民。”

    所以,你当然可以继续使用Objective-C进行开发。不过,苹果似乎在鼓励你在新项目中使用Swift,而不希望你用Objective-C编写所有代码。

虽然这是纯粹的炒作,大家都在猜测苹果会将逐渐放弃Objective-C作为今后开发的的框架和API,有一天Objective-C的甚至可能被弃用。

什么是Playground?

    Playgroud是一个文件,在这里你可以编写代码并立即看到结果。他是学习Swift或新的API、编写原型代码或者开发算法最佳的地方。当你说你要去操场(Playground)上时要小心周围的孩子,这等于把你的孩子弄哭后带他们到公园坐下来的,而不是电脑前!

NDA解禁了吗?

我们目前对NDA的理解是这样的:

  • 您可以免费发布Swift beta/iOS 8 beta的文章/教程。因此,我们在这里发布了一堆免费的Swift教程!

  • 您不能发布Swift beta/iOS 8 beta的截图。因此,在我们的教程中,我们将不发布Swift beta/iOS 8 beta的截图或视频,直到NDA被解除。

  • 对于Swift beta/iOS 8 beta你不能发布付费内容。因此,我们Swift的介绍、视频和教程系列是免费的,而且不会发布我们的Swift书书籍,直到NDA被解除。

如何学习Swift?

已经有很多学习Swift的资源了:

深入知识

有什么Swift可以做而Objective-C不能做的,反之亦然?

是的!Swift是一个现代化的语言引入了很多Objective-C中不支持的东西。包括命名空间,optionals,元组,泛型,类型推断,还有更多。Objective-C中也有一些“特色”是Swift所不具备的像messaging nil。推荐阅读苹果Using Swift with Cocoa and Objective-C Guide来了解更多细节 - 读这篇文章,当然了!

有没有什么API在Swift中不兼容?

到目前为止还没有,不过有些关于如何在Objective-C和Swift API之前迁移代码的一些注意事项,下面是一些例子:

  • Objective-C API返回ID,在Swift中是返回AnyObject。

  • Objective-C API返回nil,Swift将得到值为NULL的Optional,这个方式是Swift表示nil的方式。由于Swift的变量必须包含一个值,所以它使用Optional枚举从一个Objective-C API返回的结果(Objective-C的方法不保证不会返回nil)。

  • 当一个Objective-C API返回集合,在Swift中会用AnyObject表示,这是由于无法推断出存储的是什么类型(NSArray或NSDictionary)。这是一个很好的做法,可以根据你了解的API情况转换他们。考虑下面例子,一个返回NSString数组的Objective-C的方法。因为你知道返回的数组包含字符串,您可以通过以下方式安全地转换。

let fruits : [AnyObject] = // some Objective-C API that returns NSArray of NSStrings for fruit in fruits as String[] {
    println(fruit)}
  • 当SwiftAPI返回一个元组,在Objective-C将获得不到返回值!由于Objective-C中不支持元组,该方法将无法使用Objective-C代码。有一些Swift的类型Objective-C不支持。这些包括:

    • 泛型(Generics)

    • Tuples(元组)

    • Swift中定义的 Enumerations(枚举)

    • Swift中定义的Structures(结构)

    • Swift中定义的Top-level functions(顶级函数)

    • Swift中定义的Global variables(全局变量)

    • Swift中定义的Typealiases(类型别名)

    • Swift风格的variadics

    • Nested types(嵌入类型)

    • Curried functions(闭包函数)

在playground中我的println()方法输出结果在哪里?

在Xcode6-beta5中,println()方法的输出结果在playground的边栏(slidebar)显示

我怎么在playground中看值的图形?

在Playground中可以随时间变化显示值得图形,这个功能在用于可视化的算法是非常仿版。

要做到这一点,可以在playground中输入以下代码根据时间来产生值:

for x in 1..<10 {
  x
}

在侧边栏,你会看到类似“9 times”。将鼠标移到该行会显示A +按钮。单击此按钮(并确保你的Assistant Editor是打开的),你应该可以看到图形。

怎么运行REPL?  

运行在终端下面的命令来告使用Xcode6的命令行工具。

sudo xcode-select -s /Applications/Xcode6-Beta5.app/Contents/Developer/

然后运行下面命令开启Swift的REPL

xcrun swift

当你打算退出时,可以键入:exit:quit。当然也可以使用CTRL+ D按键。

是否可以使用Swift调用Objective-C代码或第三方库?如果可以,如何做呢?

可以!当第一次将.swift文件添加到Xcode项目时,Xcode会提示你是否创建一个桥接的头文件。在头文件中你可以导入需要在Swift中使用的Objective-C头文件。

然后,在Swift代码中就可以使用所有导入的类了。您可以用Swift语法来使用Objective-C代码以及系统类。

数组只能包含一种类型的对象吗?如果我想放不同的类型的对象是否可以?

在Swift中强烈建议是哟ing只包含一种对象类型的数组,如下面的代码:

var goodArray: [String] = ["foo", "bar"]

但是,在技术上仍然可以创建包含多种类型对象的数组。不过如果要这样做,你应该问自己为什么要这么做。在大多数情况下这不是最佳的方案,你可以找到更优雅的解决方案。

下面的代码是,如何在Swift中创建一个可以包含不同类型类型对象的数组,它包含的类型是AnyObject:

var brokenArray: [AnyObject] = ["foo", 1, 12.23, true]

字典是否也可以像数组一样包含多种类型对象吗?字典是否也是强类型的

是的,但同样可以使用AnyObject解决这个问题。对于字典这个方法往往是有意义的,不是所有的字典中的值都是相同类型的。考虑一个目录服务返回的JSON数据:

var employee : Dictionary<String, AnyObject> = 
        ["FirstName" : "Larry", "LastName" : "Rodgers", "Salary" : 65_000.00]

这个词典包含两个String值和一个Double。虽然这是可以实现的,你应该选择创建类来描述你的数据,而不是依靠字典。

细节问题

Swift中有等价于id的类型吗?

有的!如前所述,对应于Objective-C API返回ID,在Swift中是AnyObject。AnyObject类型可以表示任何类的实例。还有any类型可以表示任何类型的一个实例(除了函数类型)。

在Swift中是如何做到类型判断? (例如,if ([obj isKindOfClass:[Foo class]]) { … })

 可以使用is关键字检查一个变量或常量的类型。Swift是类型安全的,因此不能为将对象引用指向不同类型

var someValue : Any?
 
someValue = "String"
 
if someValue is String {
    println("someValue is a String")
} else {
    println("someValue is something else")
}

注意,如果你像下面代码这样写。

var someValue = "String"
 
if someValue is String {
    println("someValue is a String")
} else {
    println("someValue is something else")
}

编译器将会提示警告。

Playground execution failed: error: <REPL>:7:14: error: 'is' test is always true
if someValue is String {

如何在Swift的enum类型中使用位移值?(i.e. MyVal = 1<<5)

不幸的是苹果还没有明确解决这个问题。有一些传闻说他们正在努力改进。研究员教程团队成员克里斯LaPollo想出了以下解决方法:

class MyOptions {
  class var None   : UInt32 { return 0 }
  class var All    : UInt32 { return UInt32.max }
  class var First  : UInt32 { return 1 }
  class var Second : UInt32 { return 1<<1 }
  class var Third  : UInt32 { return 1<<2 }
}

使用例程:

physicsBody.categoryBitMask = MyOptions.First
physcisBody.collisionBitMask = MyOptions.First | MyOptions.Second


戴夫·劳森也写了这篇文章,你可能有兴趣阅读。希望在后面的公测版本中,我们会看到什么苹果已经解决了这个问题!

Swift如何与Grand Central Dispatch协作?

可以像Objective-C中一样使用C API

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
    println("test")
});

当处理并发问题时,也可以使用苹果提供的更高级的NSOperationQueue来处理。

有没有类似于Objective-C的国际化的宏?

类似于Objective-C的NSLocalizedString宏,你可以在国际代码使用NSLocalizedString(key:tableName:bundle:value:comment:) 方法。 tableName, bundle, 和value 参数都有默认值。所以,如果你已经习惯了使用NSLocalizedString你可以写。

NSLocalizedString("Hello", comment: "standard greeting")

我需要担心循环引用吗?

当然!当两个对象之间具有强关联时,循环引用仍然是可能发生的。为了打破循环引用你可以使用Objective-C中类似的方法。有三个关键字用于声明这些引用类型; weak 和 unowned可以用来解决循环引用问题。

  • strong:在自己的对象中应该使用strong。strong引用会使ARC保留实例,直到不再需要它们。当所有强引用都被删除时引用的实例被释放。需要注意的是,强引用默认的、隐含的,所以不需要明确申明。

  • weak:在具有独立生命周期对象之间,你应该使用弱(weak)引用。
    当您设置一个弱引用来引用一个对象时,你应该确定当内存使用过大时可以随时释放该对象。弱引用值必须始终是一个变量,使用var定义,也必须使用可选的?操作符。由于弱引用是可选的,所以当引用为nil时ARC将自动释放引用的实例。

  • unowned:你应该对具有相同生命周期的对象使用unowned引用;例如,当一个对象指向回它的owner时为了避免循环引用。unowned引用时使用的引用总会有一个值,你需要告诉ARC不设置引用为nil。unownde的行为与Objective-C中的unsafe_unretained一样。你有责任确保对象被释放后不再使用这些引用,这样做会导致应用程序崩溃。unowned引用必须设置为不可选的,并且不能被设置到nil。unowned引用会隐式地解开(implicitly unwrapped)。

分号在哪里?

在Swift中分号是可选的,并且苹果建议你停止使用他们(为了可读性)。
但是,有时Swfit任然使用分号,如for语句:

for var index = 0; index < 3; ++index { ... }

什么是与Swift编码风格的最佳实践?

我们已经创建了一个Swift编码风格指南的草稿。请注意,这是一项正在进行的工作,我们在新的Swift开发最佳实践产生时更新它!

本文链接:http://www.4byte.cn/learning/119998/swift-yu-yan-chang-jian-wen-ti.html