最近工作不是很忙,就继续学习swift,想着干学习语法提高太慢,就试着用swift写了一个2048小游戏,中间遇见的一些问题在这里记录一下:
首先自定义类就花费了很大的力气,主要是因为swift自定义类时严格控制了初始化,我想自定义一个继承自UIView的类,首先必须写这个函数:
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
require关键字表明如果子类需要添加异于父类的初始化方法时,必须先要实现父类中使用required
修饰符修饰过的初始化方法,并且也要使用required
修饰符而不是override
。如果子类中不需要添加任何初始化方法,我们则可以忽略父类的required
初始化方法:
在Objective-C中,init方法是非常不安全的:没有人能保证init只被调用一次,也没有人保证在初始化方法调用以后,实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的话,还可能会造成各种问题。虽然Apple也明确说明了不应该在init中使用属性来访问,但这并不是编译器强制的,因此还是会有很多开发者犯这样的错误。
所以Swift有了超级严格的初始化方法。一方面,Swift强化了designated初始化方法的地位。Swift中不加修饰的init方法都需要在方法中保证所有非Optional的实例变量被赋值初始化,而在子类中也强制 (显式或隐式地)调用super版本的designated初始化,所以无论如何走何种路径,被初始化的对象总是可以完成完整的初始化的。以下是我的初始化方法:
init()
{
self.number = 2
self.frameNumber = 16
for lineNumber in 0...3
{
for columnNumber in 0...3
{
let cubX = CGFloat(columnNumber)*(cubWidth+space)+space
let cubY = CGFloat(lineNumber)*(cubWidth+space)+space
let cubFrame:CGRect = CGRectMake(cubX, cubY, cubWidth, cubWidth)
self.frameArray.append(cubFrame)
}
}
super.init(frame:CGRectMake(0, 0, cubWidth, cubWidth))
self.label.text = "2"
self.label.font = UIFont.init(name:label.font.fontName, size: 70)
self.label.textAlignment = NSTextAlignment.Center
self.label.backgroundColor = UIColor.whiteColor()
self.addSubview(self.label)
}
convenience init(number:Int)
{
self.init()
self.number = number
self.label.text = "\(number)"
}
与designated初始化方法对应的是在init前加上convenience关键字的初始化方法。这类方法是Swift初始化方法中的“二等公民”,只作为补充和提供使用上的方便。所有的convenience初始化方法都必须调用同一个类中的designated初始化完成设置,另外convenience的初始化方法是不能被子类重写或从子类中以super的方式被调用的。
只要在子类中实现重写了父类convenience方法所需要的init方法的话,我们在子类中就也可以使用父类的convenience初始化方法了。
因此进行一下总结,可以看到初始化方法永远遵循以下两个原则:
对于某些我们希望子类中一定实现的designated初始化方法,我们可以通过添加required关键字进行限制,强制子类对这个方法重写实现。这样的一个最大的好处是可以保证依赖于某个designated初始化方法的convenience一直可以被使用。
在OC中,我们可以重写 set和get方法去满足我们的需求,在swift中,这方面分得更加细致。首先把属性进行了分类,分为了存储属性和计算属性。对于存储属性,只需要单纯的 存储数据,所以不需要重写get和set方法。而对于计算属性,就是需要通过计算来设置值的,需要重写,具体形式如下:
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
var number:Int
{
didSet
{
label.text = "\(self.number)"
}
}
在swift中强制类型转换通过类似这种形式:Int(要转化的变量),但如果你要将父类对象强转为子类对象的话,需要使用as,具体如下:
for cub in self.gameBackGround.subviews
{
if (cub is CYLCubView)
{
subViewArray.append(cub as! CYLCubView)
}
}
在swift中使用.sort进行排序,这里用到了闭包,还有一点不太理解,看一下别人的说法,讲得很清晰:
直接贴代码,不过多解释
//这是我们的model
class imageFile {
var fileName = String()
var fileID = Int()
}
//使用
var images : [imageFile] = []
images.sort({ $0.fileID > $1.fileID })
// 一般的代码形式
images.sort({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
// 省略(->)的形式
images.sort({ image1, image2 in return image1.fileID > image2.fileID })
// 带返回值的简单闭包形式
images.sort({ image1, image2 in image1.fileID > image2.fileID })
// 隐含参数的形式
images.sort({ $0.fileID > $1.fileID })
// 以下结果都是相同,只是书写形式不同
images = images.sorted({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = images.sorted({ image1, image2 in return image1.fileID > image2.fileID })
images = images.sorted({ image1, image2 in image1.fileID > image2.fileID })
images = images.sorted({ $0.fileID > $1.fileID })
//swift标准库
sort(&images, { (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
sort(&images, { image1, image2 in return image1.fileID > image2.fileID })
sort(&images, { image1, image2 in image1.fileID > image2.fileID })
sort(&images, { $0.fileID > $1.fileID })
//使用方法
images = sorted(images, { (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = sorted(images, { image1, image2 in return image1.fileID > image2.fileID })
images = sorted(images, { image1, image2 in image1.fileID > image2.fileID })
images = sorted(images, { $0.fileID > $1.fileID })
在项目中我的用法:
array1.sortInPlace({$0.frameNumber < $1.frameNumber})
根据数组中对象的frameNumber属性从小到大进行排序
lazy var maskView:UIView? =
{
let maskView = UIView.init(frame: CGRectMake(0, 0, screenWidth, screenHeight))
maskView.backgroundColor = UIColor.blackColor()
maskView.alpha = 0.9
return maskView
}()