感谢 Mac 君提供了 raywenderlich 的书籍的团购,一开始是 iOS 8 by Tutorials,这本书属于 iOS 开发中的提高书籍,买的的时候还存在些许犹豫,而当第二次团购是入门书籍 iOS Apprentice 时,这本书才比较适合像我这样的菜鸟,于是购入。这篇读书笔记主要是记录下自己印象比较深刻的部分。
全书共分为四章,分别是 Getting Started, Checklists, Mylocations 和 StoreSearch。这次写的是第一章的笔记。
Try to think of other things the app needs to do – no matter if you don’t actually know how to accomplish these tasks. The first step is to figure out what you need to do; how to do these things is not important yet.
Whenever I start working on a new app, I first make a list of all the different pieces of functionality I think the app will need. This becomes my programming to-do list. Having a list that breaks up a design into several smaller steps is a great way to deal with the complexity of a project.
书的开篇提到在开始做项目写代码之前先列一个 to-do list,也就是待办事项,列出要做出这个程序,需要完成哪些事情,相当于写出程序是由那几个功能性模块组成的,作者强调了,怎么做并不是最重要的,重要是先发现需要做什么,然后再将模块的实现转变为一系列小步骤,这样能够使你的整个工程看起来不那么令你感到恐惧。
Simply put, the Main.storyboard file contains the design of the view controller’s user interface, while ViewController.swift contains its functionality – the logic that makes the user interface work, written in the Swift language.
每一个页面都有自己的 ViewController,负责处理页面的逻辑部分,从 model 里拿到数据然后让页面显示出来。(MVC)
These objects communicate by passing messages to each other. When the user taps the Hit Me button in the app, for example, that UIButton object sends a message to your view controller. In turn the view controller may message more objects.
这里简单说明了组成 App 中的对象之间是通过互相发送消息来交流的,当用户点击了页面上的按钮时,对象之间就发生了消息的传递。
On iOS, apps are event-driven, which means that the objects listen for certain events to occur and then process them.
As strange as it may sound, an app spends most of its time doing... absolutely nothing. It just sits there waiting for something to happen. When the user taps the screen, the app springs to action for a few milliseconds and then it goes back to sleep again until the next event arrives.
iOS 的应用是事件驱动的,对象等待特定事件的发生并做相对应的处理(想到了 Windows 的事件监听函数了= =)
Input from the user, mostly in the form of touches and taps, is the most important source of events for your app but there are other types of events as well. For example, the operating system will notify your app when the user receives an incoming phone call, when it has to redraw the screen, when a timer has counted down, and many more.
Everything your app does is triggered by some event.
应用不仅要处理当前用户的事件,还要对系统事件做出回应。
The difference between the two is that a function doesn’t belong to an object while a method does. In other words, a method is exactly like a function – that’s why you use the func keyword to define them – except that you need to have an object to use the method. But regular functions, or free functions as they are sometimes called, can be used anywhere.
函数(function)和 方法(method)的区别。
在看 Stanford iOS 公开课 (2015) 的第一课中提到:
Method is a function in class.
在看 Swift Programming Language 时,书中提到了 function 和 method 的另外一个重要区别:
Parameters names in functions are used only within the functions, but parameters names in the methods are also used when you call the method (except for the first parameter). By default, a method has the same name for its parameters when you call it and within the method itself. You can specify a second name, which is used inside the method.
类中的方法和一般的函数有一个重要的区别,函数的参数名只在函数内部使用,但是方法的参数名需要在调用的时候显式说明(除了第一个参数)。默认情况下,方法的参数名和它在方法内部的名字一样,不过你也可以定义第二个名字,这个名字用在方法内部。
PS:感谢@未来眼之老码团队和梁杰_numbbbbb发布的中文版,看不懂原文的时候再看看翻译一般就能看懂了
简单明确。
There are three possible scope levels in Swift:
Global scope. These objects exist for the duration of the app and are accessible from anywhere.
Instance scope. This is for variables such as currentValue. These objects are alive for as long as the object that owns them stays alive.
Local scope. Objects with a local scope, such as the slider parameter of sliderMoved(), only exist for the duration of that method. As soon as the execution of the program leaves this method, the local objects are no longer accessible.
全局变量、实例变量,局部变量的定义。
全局变量的作用于整个 App,在程序的任何地方都可以访问到它。
局部变量一般是方法的一部分,或者作为方法/函数的参数,它们在方法/函数中被创建出来,它们的作用域仅限于方法/函数的范围内,当方法/函数执行完毕时局部变量即被销毁。
实例变量一般在对象内,它的作用域存在于整个对象,如果它所属的对象不被销毁则这个实例变量将一直存在。
变量前面有 @IBOutlet
即表明这个变量是一个 outlet,能够被Interface Builder 发现并且和某一个 UI 对象连接。
Code duplication is a big source of bugs, so if you need to do the same thing in two different places consider making a new method for it.
The name of the method also helps to make it clear what it is supposed to be doing.
Well-written source code speaks for itself. I hope I have convinced you of the value of making new methods!
写的好的源代码是会自己说话的~想到之前在《黑客与画家》里看到的一句话:程序首先是给人阅读的,然后才是给机器执行的。(大意是这样,和原文有些许偏差)
Normally you don’t need to use self to send messages to the view controller, even though it is allowed. The exception: inside closures you do have to use self to refer to the view controller.
This is a rule in Swift. If you forget self in a closure, Xcode doesn’t want to build your app
在第一章中为了使用户在按下通知中的按钮之后 slider 再返回初始位置(默认是通知显示后马上执行后面的更新代码,即 slider 返回)而使用了闭包,具体代码如下:
let action = UIAlertAction(title: "OK", style: .Default,
handler: { action in
self.startNewRound()
self.updateLabels()
})
当用户按下 OK 按钮后,参数 handler 后的代码将自动被执行,这样如果用户不点 OK 按钮,则 slider 将会停在这一次的位置上而不是马上返回。
闭包的概念我不是很懂,文章这里建议便于理解,可以简单地把闭包看作是一个没有名字的方法。
通常在对象内调用自己的方法是可以不用在方法名前加上 self.
的,但是如果这些方法是在闭包中调用时(如上)必须在方法名前加上self.
,否则运行时会报错。
当说到 App 的关于界面时,用户看完关于界面,应该有一个按钮点击离开,会用到 dismissViewControllerAnimated
这个方法:
@IBAction func close(){
dismissViewControlledAnimated(true, completion: nil)
}
}
// 当方法的第一个参数设为 false 时,将没有翻页的动画效果,立即返回主界面,这并不是非常友好的方式。
- 在添加一个新页面时,如果发现 action 连接时找不到对应的函数名,可以检查下 Identity inspector,看下 Custom Class 下是不是对应的View Controller,如果不是,改成对应的,应该就能解决。
Info.plist
- Most of the options from the Project Settings screen, such as the supported device orientations and whether the status bar is visible during launch, get stored in your app’s Info.plist file.
- Info.plist is a configuration file inside the application bundle that tells iOS how the app will behave. It also describes certain characteristics of the app that don’t really fit anywhere else, such as its version number.
- With previous versions of Xcode you often had to edit Info.plist by hand, but with Xcode 6 this is hardly necessary anymore. You can make most of the changes directly from the Project Settings screen.
- The Info.plist file is just a list of configuration options and their values.
关于图片素材
第一章中有介绍针对不同的设备,我们的素材应该对应 XCode 中的哪些参数:
1x 是给低分辨率设备使用的,唯一还能运行 iOS 8 的设备是 iPad2 和 iPad mini。
2x 是给 Retina 设备使用的,包括 4s, 5, 5c, 5s 和 iPhone 6 以及 Retina iPad,它的大小是 1x 的两倍
Retina 4 2x 是专门给4寸的 iPhone 使用的(5, 5c, 5s),这类素材的文件名结尾常常是
-568h@2x
3x 是给 Retina HD 设备使用的(iPhone 6 Plus)
在 storyboard 中,把装有背景图的 Image View 移到 View 的最顶层来确保不会盖住其他元素。
第一章中有关美化 Slider 的代码(只能用代码= =)
let thumbImageNormal = UIImage(named: "SliderThumb-Normal") // 加入未被选中的滑块图片
slider.setThumbImage(thumbImageNormal, forState: .Normal) // 应用到 slider 上
let thumbImageHighlighted = UIImage(named: "SliderThumb-Highlighted") // 加入选中的滑块图片
slider.setThumbImage(thumbImageHighlighted, forState: .Highlighted) // 应用到 slider 上
let insets = UIEdgeInsets(top: 0, left: 14, bottom: 0, right: 14) // 设置图像的伸缩距离,图像可在 UIEdgeInsets 函数的四个参数形成的矩形范围内伸缩
// 添加在滑动范围内的图片,即滑块左侧;设置图片伸缩范围(insets);添加到 slider 上
if let trackLeftImage = UIImage(named: "SliderTrackLeft") {
let trackLeftResizable =
trackLeftImage.resizableImageWithCapInsets(insets)
slider.setMinimumTrackImage(trackLeftResizable, forState: .Normal)
}
// 同上,这次添加在滑动范围外的图片,即滑块右侧
if let trackRightImage = UIImage(named: "SliderTrackRight") {
let trackRightResizable =
trackRightImage.resizableImageWithCapInsets(insets)
slider.setMaximumTrackImage(trackRightResizable, forState: .Normal)
}
关于第一章 Auto Layout 的部分,书中提的不多,步骤很详细,跟着做,也实现了,但不是非常理解(−_−;),幸好在书后面的几章中将继续学习……
The way you use Auto Layout is by defining relationships between your different views, the so-called constraints. When you run the app, UIKit evaluates these constraints and calculates the final layout of the views. This probably sounds a bit abstract, but you’ll see soon enough how it works in practice.
There are different types of constraints. The Horizontal Space and Vertical Space constraints you’re using here make sure that the sides of two views stay glued together with a certain amount of spacing between them.
大致应该就是说通过添加一些限制来保证不同的元素之间始终有一定的空间,面对不同的屏幕大小,UIKit 估算这些限制使各元素间的相对位置保持不变最终显示出界面。
As soon as you add just one constraint to a view, Xcode will no longer add automatic constraints to that view. From then on you’re responsible for adding enough other constraints so that UIKit always knows what the position and size of the view will be.
当在界面中添加了限制之后,Xcode将不再自动添加缺省的限制,所以需要开发者自己把剩下的限制加上保证界面的一致。