最近工作不是很忙,就继续学习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 }()