为了账号安全,请及时绑定邮箱和手机立即绑定

【译】学习使用Swift编写iOS app教程4:你的第一个app

标签:
iOS

写在前面:
刚刚开始学习Swift开发,很幸运的是在网上闲逛的时候看到了Ray Wenderlich的这些关于iOS开发的教程,写的非常详尽,还很有趣,不时会搭配一些很贱的小表情,非常对我的胃口:-)在此对其进行一些翻译,纰漏之处,欢迎大家指正。
——Schuming


Update note: This tutorial was updated for iOS 9 and Swift 2 by Brian Moakley. Original post by Mike Jaoudi and Ry Bristow.
恭喜,你来到了教程系列的第四部分!
在教程的第一部分,你学习了通过Swift语言编程的基础知识,包括变量,if/else语句,循环,可选类型等等.
在教程的第二部分,你将新的Swift技能应用到一个简单的猜数字游戏中.
在教程的第三部分,你创建了一个简单的命令行app来记录people对象的名字和年龄.
在第四部分里,终于要制作你的第一个iPhone App了.
在这个教程中,你将学习到怎么去创建一个叫做Tap Me的游戏!这个游戏的目的是要你在30秒内,尽可能多的点击一个按键.


开始
首先,打开Xcode并选择Create a new Xcode project.
图片描述
然后,选择 iOS > Application > Single View Application and hit Next.
图片描述

按照如下内容填写项目选项:

  • Product Name: Tap Me
  • Organization Name: 这项可以为空,或者你也可以输入你的公司名称
  • Organization Identifier: 输入com.yourname, 比如com.rybristow
  • Language: Swift
  • Devices: iPhone

图片描述


串连图(Storyboards)
你会注意到,这个项目的初始文件和你的Command Line Tool App有所不同. 你最先关注的应该就是Main.storyboard了.
图片描述
当你点击这个文件后,你将打开一个图形用户界面(Graphical User Interface,GUI),它显示的是app运行后iPhone将显示的界面.
图片描述

注意:你可能会奇怪,为什么这个界面看起来是一个正方形,而不是iPhone的尺寸.在iOS开发中,你的目标是将你的apps设计为可以适应不同屏幕的尺寸-这叫做自适应布局(Adaptive Layout).
一般来说,你将会以“远离顶部位置(stay this far away from the top)”或"停留在中心位置(stay centered)"这样的规则来布局你的用户界面中的元素,通过这样的方式,可以让app工作在iPhone5到iPhone 6 Plus等等屏幕大小不一的设备上.

现在,这个app是一片空白的.为了做些改变,你需要确保工具菜单(Utilities Menu)是打开的.选中并打开.
图片描述
接下来,选择属性检查器(Attributes Inspector)
图片描述

它可以让你去查看和修改视图控制器(View Controller)中的不同属性.要查看属性,需要先点击view
将背景颜色由白色改为绿色.
图片描述
现在,在上方的菜单中选择iPhone 6仿真器并运行app-这样你可以看到程序运行后的样子.构建(build)和运行(run)需要花费一段时间,因此要耐心一点.当它最终运行起来后,你应该看到一个弹出的窗口,它是一个正在运行当前app的模拟的iPhone界面.
图片描述


在界面中添加标签(Adding Labels to the Screen)
绿色的界面看起来不错,但是如果你的界面中没有用户交互的内容,你的app就毫无用处.要添加一些组件,打开工具菜单(Utilities Menu)中的组件库(Object Library).你添加的第一个对象是标签(Label)组件.标签(Label)可以被程序用来承载文本内容.浏览组件库,找到Label.
图片描述
将它拖拽到界面中并将它布局在顶部的中心位置.
图片描述
你可以使用属性检查器(Attributes Inspector)来修改Label的标题(title),也就是Label上显示的内同. 将它改为“Time: 30”.
图片描述
到了这里,你的label可能看起来像是被截掉了一段.为了改变这个情况,点击你的label并选择Editor\Size to Fit (或者敲=号).
现在运行你的app来看一下是这样的.
图片描述
通过串联图(storyboard), 这个标签看起来没有居中是不是? 这个问题是因为并非每一个iOS设备都有相同的尺寸规格,所以有时候对尺寸的适配会非常混乱.你需要做的就是给label添加一个布局约束(constraint)来保证它处于屏幕的中心位置.
点击Label,然后选择屏幕底部的Align按键并选择Horizontal Center in Container 并且 Add 1 Constraint.
图片描述

这决定了label在横向上的位置.你还需要选定它在纵向上的位置.点击屏幕底部的Pin,通过红色顶针来固定当前位置与顶部的相对距离,点击 Add 1 Constraint:
图片描述
添加了布局约束后的label可能会带有一条向外扩展的橙黄色的线.这是因为label的位置跟布局约束建议位置不同产生的.
图片描述

如果确是这样, 点击右手边稍下面一些的三角型图标(triangle icon) ,在View ControllerAll Views中, 选择Update Frames选项.
图片描述
现在,创建另一个Label对象并将它放置在界面的底部来显示分数.两个不同的地方是,你将希望字体大小(font size)为40,线宽(Lines)为2.将布局(Alignment)设置为中心对齐(Center).

图片描述
尺寸检查器中(Size Inspector), 将高度(height)设置为130点高.
图片描述
你还需要添加一些布局约束(constraints) . 首先你要在横向上将它放置到中心位置.在score label被选中的情况下,点击Align按键,选择Horizontal Center in Container 然后 Add 1 Constraint.
接下来,点击Pin按钮. 添加一个bottom pin, 选择Height. 将Height设置为130.最后的点击 Add 2 Constraints button.
如果你看到橙黄色的线,点击右下角的三角形图标,在All Views in View Controller 部分, 选择 Update Frames 选项:
图片描述
Build然后 run, 现在你的labels应该很完美的居中了:
图片描述


添加一个按键
在屏幕上添加最后一个组件.使用Object Library来添加一个组件并把它放到屏幕正中间.
图片描述

不要忘记给button添加constraints,横向和纵向都放到中心位置.
图片描述
通过 Attributes inspectortitle改为Tap Me! 并将background设为white.
为了让你的button在白色背景上更醒目一点,你要通过不同的constrains对它进行一些拉伸.这次,要点击Pin然后选择WidthHeight方框.将width设置为167,height设置为113.
图片描述
如果出现了橙黄色的线,就去执行前面说过的Update Frames.
你的button应该是一个块漂亮的并足够大的可点击区域.Build并且run,你的app看起来应该是这样的:
图片描述
你可以点击button,现在什么都不会发生.我们来做点改变!


关联Views和代码(Linking Views to Code)
现在你已经在Storyboard中排列好了views.你需要将他们与代码关联起来.每个iOS app中的"screen"都由View Controller类控制. Xcode已经在模板中为你创建了一个 – ViewController.swift.在这款游戏里,你得为你的labels在这个类中添加两个属性(properties),这样你就可以通过编程来更新labels.将下面的属性添加到ViewController.swift中的ViewController类中:

@IBOutlet var scoreLabel: UILabel!
@IBOutlet var timerLabel: UILabel!

这两行代码创建了两个UILabel属性.你需要把你在Storyboard中创建的views和这些属性关联起来.通过@IBOutlet 关键词来标记这些属性后,storyboard 编辑器会识别到他们.

注意:你可能注意到了,你在标记这些labels时,在结尾使用了一个感叹号.这是将label声明为隐式解析可选类型(implicitly unwrapped optionals).在你操作这些属性前,编译器会自动解析这些可选类型属性,你可以像操作正常类型的变量一样操作他们(尽管他们是可选类型).
在这里这样做事完全没问题的,因为你一定会将它们赋值给你之前在storyboard中创建的views,所以他们一定不会是nil.

类似的情况,当按键被按下时,你希望调用一个method.因此在 ViewController 类中添加这些代码:

@IBAction func buttonPressed()  {
  NSLog("Button Pressed")
}

类似于 @IBOutlet, @IBAction会让storyboard 编辑器识别到这些方法, 因此你可以将按键点击事件跟它关联起来.
试着关联这些属性和方法!打开 Main.storyboard, 查看打开的文件树,要链接labels的话,你需要在按住CTRL键的情况下,将文件树的中的View Controller拖拽到Time label顶部.
图片描述
会弹出一个列有Outlets的黑框.选择timerLabel.这是你之前在ViewController.swift中创建的UILabel组件.
图片描述
现在为score label重复这个操作,将他与scoreLabel关联起来.
为了将button与buttonPressed()方法关联起来,你需要将刚才的过程反向操作一遍.按住CTRL的情况下,将Storyboard中的button拖拽到文件树中的View Controller上.
图片描述
然后,选择buttonPressed().

图片描述
现在,试着运行app并点几下button.通过在buttonPressed()中使用NSLog语句,每次你点击button时,屏幕底部的console上都会有一句输出.
图片描述


操作Labels
button的真正目的不是向终端中进行输出,而是在每次被点击时,让中心的label显示的次数累加.首先,你要学着怎么操作label中的文本.
有个好消息是-这很简单!将buttonPressed()中的函数体替换为下面的内容:

scoreLabel.text = "Pressed"

现在,当你运行你的app并点击button时,屏幕底部的文本会改变为"Pressed".
为了将这个方法应用到scroeLabel上,让它实时显示分数.你需要再做一点工作:


实时显示分数
为了实时显示分数,你需要先创建一个变量.靠近类代码段的上方,两个 @IBOutlet 声明的下面,创建一个叫做count的属性来实时保存score值.

var count = 0

下一步是向buttonPressed()函数顶部添加一行代码,实现count的加运算.

count++

这行代码是下面的简化版:

count = count + 1

现在将scoreLabel中设置text的语句改为:

scoreLabel.text = "Score \n\(count)"

运行你的app来看一下效果.当你点击button时,屏幕底部的label会实时显示你的分数.你的app正在一步一步编程一个可以真正玩起来的游戏!


使用Timer
为了使timer能正确的服务于app,你需要创建两个属性.其中一个是实时保存seconds的变量,另一个是用来计数的NSTimer.在count的声明下面添加这些声明:

var seconds = 0
var timer = NSTimer()

为了使用这些变量,你需要创建两个方法.第一个是setupGame().在类代码段底部添加这个方法的实现:

func setupGame()  {
  seconds = 30
  count = 0

  timerLabel.text = "Time: \(seconds)"
  scoreLabel.text = "Score: \(count)"
}

这部分代码会在游戏开始时,将所有变量设置为原始值并更新labels.如果你不包含这部分代码,seconds会一直减小而负于0,分数也会一直增长,游戏永远不会重置.
接下来要在 setupGame() 中做的就是开启 timer. 你需要使用scheduledTimerWithTimeInterval()方法来让控制timer.在setupGame()中添加这些代码:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("subtractTime"), userInfo: nil, repeats: true)

现在,通过添加下面的代码,来保证你在viewDidLoad()方法中调用了setupGame():

setupGame()

下面你要实现的方法叫做 subtractTime(). 你会注意到,你在setupGame()中使用timer时,已经在selector项中使用到了这个字段.它正式指向这个方法的.这个方法会用以减少seconds变量,更新timerLabel,然后在timer变为0时触发一个alert.
你要做一些你所熟知的事了:给seconds做减运算,更新timerLabel,创建一个if语句来处理sceonds变为0的情况.

func subtractTime() {
  seconds--
  timerLabel.text = "Time: \(seconds)"

  if(seconds == 0)  {

  }
}

首先要向if语句中添加的内容是停止timer,放置计数负于0.添加下面的代码:

timer.invalidate()

Buildrun, 倒计时开始了!
图片描述


红色警报!
接下来,你要学习怎么操作alerts.当你完成你的alert代码后,应该是这样的:

图片描述
开始吧.首先要创建一个 UIAlertController. 在if语句中,把这行代码添加到invalidate()后面.

let alert = UIAlertController(title: "Time is up!",
 message: "You scored \(count) points",
 preferredStyle: UIAlertControllerStyle.Alert)

这行代码决定了alert的样子.它为alert选择了title,message,和style.
接下来,你需要调整button的显示内容和功能.添加一个addAction().在alert声明后添加这行代码.

alert.addAction(UIAlertAction(title: "Play Again", style: UIAlertActionStyle.Default, handler: {
  action in self.setupGame()
}))

如果你仔细的研究这行代码,你会发现它使用了title来决定button的显示内容,并且通过handler来让button被按下时调用setupGame()函数.
最后一行代码!这行代码用来告诉app去显示UIAlertController.他使用presentViewController().在alert.addAction(...)后添加这行代码:

presentViewController(alert, animated: true, completion:nil)

现在运行你的第一个iPhone app,尽情的玩吧.你能超过我的分数吗?:]
图片描述


接下来做些什么
最终的项目代码在这里.
现在准备好学习教程中的下一部分吧.你将学习到怎么更改现在的界面,并让它看起来更吸引人.
有问题的话,欢迎来论坛讨论!

点击查看更多内容
7人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Linux系统工程师
手记
粉丝
9
获赞与收藏
211

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消