本文概述
- 设置环境
- 语言基础和语法
- 使用Swift创建iOS应用程序
Swift是Apple用于为本机iOS应用程序编程的新语言选项。它是对Objective-C的补充, 而且这种情况将持续一段时间, 现在是版本2, 没有比这更好的时间来学习新语言了。
Objective-C开发人员会发现许多与其他功能的相似之处, 例如类型推断, 强类型输入, 不依赖头文件, 泛型等等。
在本教程中, 我将向你展示如何开始使用Swift 2开发iOS应用程序。我将向你展示如何设置开发环境, 研究语言基础以及将语法与Objective-C, JavaScript和C#进行比较。在本教程的最后, 你将使用Swift创建一个简单但完整的iOS应用程序。
在许多情况下, Objective-C, C#和Swift共享相似的语法, 请参考此文件以获取完整参考。
设置环境 与Objective-C一样, Swift需要最新的Mac和Xcode。在撰写本文时, 最新版本的Xcode 7.2是从Mac App Store下载的。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351Rb7-0.png)
文章图片
该文件下载量很大, 大约为2.5 GB, 因此可能需要一段时间。下载完成后, 打开“应用程序”目录并启动Xcode。安装升级时所需的任何其他组件。如果你安装了以前版本的Xcode, 它将更新为最新版本。
现在你可以开始使用Swift进行探索和开发了。
语言基础和语法 让我们看一下语言语法, 与Objective-C的区别以及它与其他现代语言的比较。
由于无法在本教程中深入介绍Swift的所有方面, 因此我将使用简单的示例来展示高级概念。
如果你想继续, 请打开Xcode, 选择“游乐场入门”, 然后键入每个示例以查看运行情况。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351RX0-1.png)
文章图片
你可以从GitHub下载我们将尝试使用的代码以快速参考。
变量和常量
要在Swift中声明变量, 请使用关键字var:
var number = 1
用其他语言:
目标C
int number = 1;
C#
var number = 1;
Java脚本
var number = 1;
你可以看到Swift语法有多么相似, 唯一的区别是声明的末尾缺少分号。
与Objective-C的主要区别在于, 你不必定义变量类型, 因为Swift使用类型推断, 并且能够理解变量由于其初始值而为数字。
你可以根据需要定义类型:
var number: Int = 1
让我们在Swift中声明一个字符串变量:
var language = "Swift"
在这里, Swift中的声明看起来更加简洁, 几乎与C#和JavaScript相同。与Objective-C相比如何?
NSString *language = @"Swift";
使用Swift, 不需要使用内存指针(*)或在字符串值前加上@符号。
如果你使用的是Foundation框架, 则无论如何使用NSString都可以使用Swift字符串, 并且可以访问整个NSString API
Swift中的常量可以使用let关键字声明:
let language = "swift"
要么
let language: String = "Swift"
在其他语言中, 相同的声明如下所示:
目标C
NSString*const language = @"Swift";
C#
const string language = Swift";
使用Swift可以在声明常量时进行类型推断。
在Swift中使用变量与其他语言没有什么不同, 但是它有一个简单的方法可以让你在字符串中添加值:
var designers = 4
var developers = 4var teamSize = "The team has \(designers + developers) members"
数组
在Swift中, 你可以使用方括号[]创建数组和字典, 并通过在这些括号中编写索引或键来访问它们的元素。
var arr = ["first" , "second"]
在其他语言中, 相同的声明如下所示:
目标C
NSArray *arr = @[@"first", @"second"];
C#
var arr = new[] { "first", "second" };
的JavaScript
var arr = ["first" , "second"];
你可以使用索引值访问数组中的项目:
var order = arr[0]
并使用以下值设置值:
arr[0] = "zero"
该代码在Javascript和C#中是相同的, 但语句末尾使用分号。
目标C
NSString *order = arr[0];
你可以使用for item循环枚举数组:
for item in arr {
// do something
}
在其他语言中, 相同的声明如下所示:
目标C
for(NSString *item in arr)
{
// do something
}
C#
foreach (var item in arr) {
// do something
}
的JavaScript
for (index = 0;
index <
order.length;
++index) {
//do something
}
要将另一个项目添加到数组, 请使用+ =运算符:
arr += ["fourth"]
或附加函数:
arr.append("fifth")
辞典
通过定义键值对在Swift中声明字典。声明一个空字典时, 你必须定义键的类型和值。
var dict = Dictionary<
String, String>
()
你可以声明和分配值:
var dict = ["MEL": "Melbourne", "SYD": "Sydney"]
在其他语言中, 相同的声明如下所示:
目标C
NSDictionary *dict = @{
@"MEL" : @"Melbourne", @"SYD" : @"Sydney"
};
C#
var dict = new Dictionary<
string, string>
{
{ "MEL", "Melbourne" }, { "SYD", "Sydney" }
};
要从词典中访问项目, 请使用:
var entry = dict["MEL"]
在其他语言中, 相同的声明如下所示:
目标C
NSString *entry = dict[@"MEL"];
C#
var entry = dict["MEL"];
要将项目设置或添加到词典中, 请使用:
dict["PER"] = "Perth"
在其他语言中, 相同的声明如下所示:
目标C
dict[@"PER"] = @"Perth"
C#
dict["PER"] = "Perth";
要遍历字典, 请使用:
for (cityCode, cityName) in dict {
print("\(cityCode) : \(cityName)")
}
cityCode变量将包含键, cityName变量将包含值。
在其他语言中, 相同的声明如下所示:
目标C
for (id key in dict) {
NSLog(@"key: %@, value: %@", key, dict[key]);
}
C#
foreach(var item in dict) {
var cityCode = item.Key;
var cityName = item.Value;
}
循环
你已经了解了如何创建项目, 让我们看一下如何遍历它们。
首先, for循环语法:
for var number = 1;
number <
5;
number++ {
//do something
}
如预期的那样, 你指定一个值并递增直到满足条件。 Objective-C和C#语法几乎相同, JavaScript也几乎相同, 但是省略了变量类型。
你可以使用Swift for in变体来获得相同的结果:
for number in 1...5{
//do something
}
Swift创建数字变量并在迭代指定值时自动分配一个值。 1…5是一个封闭范围, 包括从1到5的数字。
使用先前创建的数组, 你可以使用此语法在数组中的城市上进行迭代。
for city in arr {
print(city)
}
Swift提供了一段时间重复循环, 其语法几乎与Objective-C, C#和JavaScript相同:
while number <
10
{
print(number)
number++
}
while语句之后的变量是布尔值, 并且代码在评估为true时将执行。
重复循环的行为相同, 但是可以确保代码在评估条件之前至少执行一次。
var number= 9
repeat {
print(number)
number++
}
while number<
10
此示例确保在使用while语句对数字值进行增值和评估之前, 先显示该数字值。
有条件的
循环控制代码中的重复任务, 而if和switch语句控制流程。
Swift中的if语法可以带括号, 但是是可选的, 因此你可以使用任何喜欢的样式。
if city == "MEL" {
print("Melbourne")
}
要么
if (city == "MEL") {
print("Melbourne")
}
if语句后可以跟一个else if或else。
if city == "MEL" {
print("Melbourne")
} else if city == "SYD" {
print("Sydney")
} else {
print("Perth")
}
Swift中的Switch语句后面要进行大小写验证, 但是因为没有隐式的穿通, 所以不需要break语句。这意味着一旦案例评估为真并执行, 下一个案例将不会评估。但是, 需要执行默认操作。
switch city {
case "MEL":
print("Melbourne")
case "SYD":
print("Sydney")
default:
print("Perth")
}
case语句可以包含多个用逗号或范围分隔的值。使用Swift, 你可以在switch语句中使用NSString, 而Objective-C则不可能。
功能
函数是一个涉及较大的主题, 但是基础知识很有用, 因此你可以声明和使用它们。
在Swift中使用关键字func声明一个函数:
func sayName() {
print("Patrick")
}
通过指定变量名称和类型, 在括号内传递参数。
func sayName(name: String) {
print(name)
}
你可以传递以逗号分隔的多个参数。
func sayName(name: String, lastName: String) {
print("\(name) \(lastname)")
}
通过在参数后添加-> 并指定返回类型来声明返回结果的函数。
func createName(name: String, lastName: String) ->
String {
return "\(name) \(lastname)"
}
使用Swift创建iOS应用程序 学习新的编程语言最好通过编写代码和创建应用程序来实现。因此, 让我们使用Swift创建一个简单的iOS应用程序。
该应用程序将连接到TheMovieDB API, 请求即将上映的电影的列表, 下载JSON结果, 将其解析为Dictionary和Arrays, 然后将此数据填充到Table View中。
为了使本教程保持简单, 它将涵盖一些常见任务, 例如创建UI元素并将其与代码连接, 使用多个控制器, 委托和协议, 并展示如何使用Swift进行异步操作, 这是该语言的优势所在。
开始之前, 请从themoviedb.org网站注册并请求应用程序API密钥。如果你还没有帐户, 请注册, 打开你的帐户页面, 并在API部分中生成一个新密钥。
该应用程序的最终代码在GitHub上, 并且我已经为每个阶段创建了分支。
让我们开始吧。
打开Xcode, 创建一个新项目, 在iOS部分中选择一个视图应用程序, 然后单击下一步。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351T4A-2.png)
文章图片
我将我的项目命名为UpcomingMovies, 然后选择Swift作为语言。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351T338-3.png)
文章图片
单击下一步, 然后选择保存项目的位置。
现在, 通过选择Xcode中的Main.storyboard文件并从对象库中拖动一个表视图对象, 来创建一个表来显示应用程序数据。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351TN3-4.png)
文章图片
要访问代码中的表, 你需要创建一个委托, 一个数据源和一个出口。
选择情节提要文件, 按住控制键, 然后单击并从“表视图”拖动到“视图控制器”, 然后在弹出菜单中选择数据源。重复该过程, 然后选择委托选项。
要创建出口, 请选择视图-> 助手编辑器-> 显示助手编辑器菜单项。你将看到一个新部分, 其中显示了ViewControler.Swift文件中的代码。
选择表和这次的保持控件, 然后单击并从“表视图”拖动到代码窗口, 在类声明下释放。
给Outlet起一个名字, 我使用了appTableView, 然后单击connect。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351QN9-5.png)
文章图片
完成UI剩下的最后一项任务是。这是为了创建一个原型单元格, 该单元格将包含影片详细信息文本, 并将重新用于表中创建的每个单元格。
为此, 选择“表视图”, 然后在属性检查器中, 将原型单元格的数量更改为1。然后单击该单元格, 将“样式”更改为“字幕”, 并为其指定MovieResultsCell的标识符。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351V914-6.png)
文章图片
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351Q359-7.png)
文章图片
好了, 是时候与Swift一起玩了。
首先, 你必须配置故事板前面连接的数据源和数据集。
在ViewController.swift中, 更改该类:
class ViewController: UIViewController {
对此:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
现在, 通过创建所需的方法来实现上面添加的2个新协议。
将以下代码行添加到ViewController.swift文件。
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) ->
Int {
return 1;
}func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
let cellIdentifier: String = "MovieResultsCell"let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier)cell.textLabel?.text = "Test"
cell.detailTextLabel?.text = "Test details"return cell
}
第一种方法定义表中的行数, 第二种方法显示数据。
你可以删除以下代码, 因为它是不必要的。
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
ViewController.Swift代码应如下所示:
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351V304-8.png)
文章图片
这样就完成了第1阶段, 继续并运行该项目, 你应该看到以下结果。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351R1U-9.png)
文章图片
现在该连接到我们的API并检索结果了。该代码应通用且可重复使用。目的是传递URL作为参数, 获取结果, 解析JSON并返回包含数据的数组。
然后, 可以将该代码重新用于后续对其他URL的API调用。
右键单击导航窗格中包含ViewController.swift的文件夹, 然后选择“新建文件”, 以创建一个新类。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351ST3-10.png)
文章图片
选择Cocoa Touch Class, 单击Next并为其赋予一个有意义的名称, 我使用了APIController。保留以下默认选项。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351Q934-11.png)
文章图片
打开文件, 然后在import UIKit行下输入以下代码。
protocol APIControllerDelegate {
func apiSucceededWithResults(results: NSArray)
func apiFailedWithError(error: String)
}
这定义了一个协议, 该协议将在ViewControler.swift中实现, 并在API调用完成后接收结果。
让我们添加将进行实际调用并处理结果的函数。
【iOS和OSX的Swift 2.0简介】在类的简化中, 添加以下代码:
var delegate:APIControllerDelegate?func getAPIResults(urlString:String) {//The Url that will be called.
let url = NSURL(string: urlString)
//Create a request.
let request = NSMutableURLRequest(URL:url!)
//Sending Asynchronous request using NSURLSession.
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) ->
Void in
do {
//Check that we have received data
guard let data = http://www.srcmini.com/data else {
self.delegate?.apiFailedWithError("ERROR: no data")
return
}
//Call the JSON serialisation method to generate array of results.
self.generateResults(data)
}
}.resume()
}func generateResults(apiData: NSData)
{
do {
//Serialise the api data into a json object
let jsonResult = try NSJSONSerialization.JSONObjectWithData(apiData, options: .AllowFragments)
//verify we can serialise the json object into a dictionary
guard let jsonDictionary: NSDictionary = jsonResult as? NSDictionary else {
self.delegate?.apiFailedWithError("ERROR: conversion from JSON failed")
return
}
//Create an array of results
let results: NSArray = jsonDictionary["results"] as! NSArray
//Use the completion handler to pass the results
self.delegate?.apiSucceededWithResults(results)
}
catch {
self.delegate?.apiFailedWithError("ERROR: conversion from JSON failed")
}
}
第一个函数采用URL, 并发出请求以从API接收数据。如果有错误, 它将执行传递错误字符串的协议的apiFailedwithError函数。成功时, 它将调用generateResults函数来解析API数据。
APIController类现在应如下所示。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351VE9-12.png)
文章图片
这样就完成了第2阶段, 如果你构建并运行该项目, 你会发现这没有什么改变。
现在该填充表中的数据了。打开ViewController.Swift并将APIControler委托添加到Class中:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, APIControllerDelegate {
在appTable出口下方, 添加以下两行:
var searchResultsData: NSArray = []
var api: APIController = APIController()
第一个变量将包含表数据。第二个变量创建用于调用其任何方法的API控制器的实例。
现在, 通过在现有tableView的下面添加以下函数来实现API控制器协议。确保用你自己的空API密钥替换。
// MARK: APIControllerDelegate//Make the API call
func getUpcomingMovies()
{
//Construct the API URL that you want to call
let APIkey: String = "" //Replace with your Api Key"
let APIBaseUrl: String = "https://api.themoviedb.org/3/movie/upcoming?api_key="
let urlString:String = "\(APIBaseUrl)" + "\(APIkey)"//Call the API by using the delegate and passing the API url
self.api.delegate = self
api.getAPIResults(urlString)
}//Handle the Error
func apiFailedWithError(error: String) {
let alertController = UIAlertController(title: "Error", message:
error, preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))self.presentViewController(alertController, animated: true, completion: nil)
}
//Handle the returned data
func apiSucceededWithResults(results: NSArray) {
self.searchResultsData = http://www.srcmini.com/results
self.appTableView.reloadData()
}
现在, ViewController.swift应该看起来像这样。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351U5L-13.png)
文章图片
让我们更改tableView函数, 并将API数据映射到行和单元格。
替换以下代码
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
let cellIdentifier: String = "MovieResultsCell"
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier)cell.textLabel?.text = "Test"
cell.detailTextLabel?.text = "Test details"return cell
}
有了这个:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
let cellIdentifier: String = "MovieResultsCell"let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)! as UITableViewCell//Create a variable that will contain the result data array item for each row
let cellData: NSDictionary = self.searchResultsData[indexPath.row] as! NSDictionary
//Assign and display the Title field
cell.textLabel!.text = cellData["title"] as? String// Construct the posterUrl to get an image URL for the movie thumbnail
let imgURL: NSURL = getPoster(cellData["poster_path"] as? String)
// Download an NSData representation of the image at the URL
let imgData: NSData = NSData(contentsOfURL: imgURL)!
cell.imageView!.image = UIImage(data: imgData)// Get the release date string for display in the subtitle
let releaseDate: String = cellData["release_date"]as! Stringcell.detailTextLabel!.text = releaseDatereturn cell
}
在此, 将API的值分配给每个单元格, 以获取电影标题, 海报和发行日期。
API并不总是返回海报的图像。这应该通过APIController中的JSON序列化来处理, 但是这种方法太复杂了, 无法在此进行介绍。因此, 出于此应用的目的, 让我们使用以下功能:
func getPoster(posterPath: String?) ->
NSURL
{
guard let posterPath = posterPath, let baseUrl: String = "http://image.tmdb.org/t/p/w300", let urlString: String = "\(baseUrl)" + "\(posterPath)", let imgURL: NSURL = NSURL(string: urlString)
else {
let defaultImageUrl: NSURL = NSURL(string: "https://assets.tmdb.org/images/logos/var_8_0_tmdb-logo-2_Bree.png")!
return defaultImageUrl
}
return imgURL
}
这将检查是否从API返回了图像路径以及为该表构??造的URL。否则, 将显示tmdb徽标。
替换以下功能
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) ->
Int {
return 1;
}
带有:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) ->
Int {
return searchResultsData.count
}
这将在表中创建与API结果一样多的行。现在表格单元已准备好接收数据, 是时候进行API调用了。
将以下行添加到viewDidLoad方法中
getUpcomingMovies()
现在, 完整的ViewController类应如下所示。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351T2O-14.png)
文章图片
在应用程序运行之前, 你需要启用“非HTTPS连接的应用程序传输安全性”, 因为tmdb API不提供加密的数据。
右键单击info.plist文件, 然后选择“打开为源代码”。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351UV7-15.png)
文章图片
在文件的底部, 关闭词典标记之前, 添加以下代码。
<
key>
NSAppTransportSecurity<
/key>
<
dict>
<
key>
NSAllowsArbitraryLoads<
/key>
<
true/>
<
/dict>
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351VG7-16.png)
文章图片
就这样, 现在运行该应用程序, 它将显示所有即将上映的电影。
![iOS和OSX的Swift 2.0简介](http://img.readke.com/220430/05351U928-17.png)
文章图片
希望你喜欢通过Apple的新语言进行的“快速”浏览, 并欢迎你在下面提出意见和问题。如果你想了解更多信息, 那么我建议你使用SitePoint的Hello World教程和Swift视频系列。
推荐阅读
- 移动应用程序构建简单的REST API
- 使用Go进行iOS和Android编程
- CSS隐藏元素的10种方法
- 处理Win10系统防火墙打开不了小技巧
- Win10浏览版10159升级失败怎样办
- Win10系统防范系统程序自动更新的2种办法
- Win10系统迅速打开技巧变成灰色、关闭不了的处理办法
- 3个步骤搞定Win10系统屏幕亮度调节不了问题
- win10系统关机变成自动重启怎样办