版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.07.18 |
前言
我是swift2.0的时候开始接触的,记得那时候还不是很稳定,公司的项目也都是用oc做的,并不对swift很重视,我自己学了一段时间,到现在swift3.0+已经出来了,自己平时也不写,忘记的也差不多了,正好项目这段时间已经上线了,不是很忙,我就可以每天总结一点了,希望对自己对大家有所帮助。在总结的时候我会对比oc进行说明,有代码的我会给出相关比对代码。
1. swift简单总结(一)—— 数据简单值和类型转换
2. swift简单总结(二)—— 简单值和控制流
3. swift简单总结(三)—— 循环控制和函数
函数
1. 函数作为参数传入另一个函数
前面在讲函数的时候,我们看到函数是可以嵌套的,还可以作为返回值返回,这里我们讲另外一种情况,那就是函数作为参数进行传递,也就是说,函数的参数是另外一个参数。
下面我们就看一下 swift
中的代码。
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
//函数作为参数进行传递
let numbers = [20, 15, 18, 9]
let matchCondition = match(list: numbers, condition: lessThan)
print(matchCondition)
}
//函数作为参数进行传递
func match(list : [Int], condition:(Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false;
}
func lessThan(number : Int) -> Bool {
return number < 18
}
2. 函数的本质
函数的本质其实就是一种特殊的闭包,可以使用{}
来创建一个匿名闭包,使用in
将参数和返回值类型声明与闭包函数体进行分离。
//函数实质上就是闭包
numbers.map({
(number : Int) -> Int in
let result = number * 3
return result
})
如果一个闭包的类型已知,比如作为一个回调函数,你可以忽略参数的类型和返回值,单个语句闭包会把它语句的值单做结果返回。
let mappedNumbers = numbers.map({number in 3 * number})
可以通过参数位置而不是参数名字来引用参数,这个方法在非常短的闭包中非常有用,当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面。
let sortNumbers = sorted(numbers) {$0 > $1}
类
1. 类的创建
使用class
和类名创建一个类,类中属性的声明和常量、变量声明一样,唯一的区别是它们的上下文是类,同样,方法和函数声明也一样。
下面看一下代码
class name{
var number = 0
func myname() -> String {
return "John"
}
}
要创建一个类的实例,在类名后面加上括号,使用点语法来访问实例的属性和方法。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
//类实例化
var nameInstance = name()
nameInstance.number = 10
var nameFunc = nameInstance.myname()
print(nameFunc)
}
}
下面我们就直接看输出
John
2. 构造器
一个构造函数来初始化实例,使用init
来创建一个构造器。
下面看代码。
class NamedShape{
var numberOfSlides : Int = 0
var name : String
init(name : String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSlides) sides."
}
}
这里self
被用来区别实例变量,当你创建实例的时候,像传入参数一样给类传入构造器参数,每个属性都需要赋值——无论是通过声明(就像numberOfSlides
)或者是通过构造器(就像name
)。
如果你需要在删除对象之前进行一些清理工作,使用deinit
创建一个析构函数。
3. 子类的定义
子类的定义就是在其类名后面加上父类的名字,用冒号分割,创建类的时候并不需要一个标准的根类,所以可以忽略父类。
我们先看一下swift
中是如何定义子类的,看代码。
class JJSwiftVC: UIViewController
{
}
上面就是定义了一个子类JJSwiftVC
,再比如
class name{
var number = 0
func myname() -> String {
return "John"
}
}
这个类就没有指定父类。
那么我们在看一下oc
中子类的定义,看代码。
#import
@interface JJOCVC : UIViewController
@end
我们可以得到如下结论:
- oc和swift子类和父类之间都是以冒号隔开。
- oc中继承父类是写在
.h
文件中,swift则不分文件。 - oc在新建文件的时候就要指定父类,且不能省略,swift可以不知道根类。
4.子类重写父类的方法
swift
和oc
一样,子类可以重写父类的方法,swift
中子类要重写父类的方法,需要用override
标记,没有这个标志就重写父类方法会报错,下面我们就看一下代码。
class NamedShape
{
var numberOfSlides : Int = 0
var name : String
init(name : String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSlides) sides."
}
}
class Square : NamedShape
{
override func simpleDescription() -> String {
return "子类在重写父类方法"
}
}
下面我们看一下oc
中是如何重写父类方法的。
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.imageArr = [self loadGifImageArr];
[self setupUI];
}
这就是典型的重写父类的方法,不用任何标志,直接在子类里实现父类的方法就是相当于重写父类的方法了。
5. 属性的getter&setter方法
下面我们看一下swift
中的setter
和getter
方法,看代码。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.permeter)
triangle.permeter = 9.9
print(triangle.sideLength)
}
}
class EquilateralTriangle : NamedShape
{
var sideLength : Double = 0.0
init(sideLength : Double, name : String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSlides = 3
}
var permeter : Double{
get {
return 3.0 * sideLength
}
set{
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral Triangle with sides of lenght \(sideLength)"
}
}
下面我们看结果输出。
9.3
3.3
上面的不难理解,getter
方法是3.0 * sideLength
,3.1 * 3 = 9.3,后面的setter方法是新值9.9 / 3 = 3.3。
这里,类EquilateralTriangle
的构造器,需要执行三步:
- 设置子类声明的属性值
- 调用父类的构造器
- 改变父类定义的属性值,其他的工作比如调用方法,getter和setter也可以在这个阶段完成。
如果不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码。可以使用willSet
和didSet
。
下面我们看一下代码。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let triangleAndSqure = TriangleAndSquare(size : 10, name : "another test shape")
print(triangleAndSqure.square.sideLength)
print(triangleAndSqure.triangle.sideLength)
triangleAndSqure.square = Square(sideLength: 50, name: "larger square")
}
}
class TriangleAndSquare
{
var triangle : EquilateralTriangle{
willSet {
square.sideLength = newValue.sideLength
}
}
var square : Square{
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size : Double, name : String) {
square = Square(sideLength : size, name : name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
上面的就是swift
中的getter和setter方法,不知道大家是否记得oc
中的getter和setter方法。
- oc中的getter方法用点语法就可以点出来。
- oc中的setter方法也可以使用点语法进行赋值。
- oc中的getter和setter方法都可以重写。
6. 类中的方法和函数
类中的方法和函数有一个重要的区别,函数的参数名只能在函数内部使用,但是方法的参数名需要在调用的时候显示说明(除了第一个参数),默认情况下,方法的参数名和它在方法内部的名字一样,不过你可以定义第二个名字,这个名字被用在方法内部,下面看代码。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
}
}
class Counter
{
var count : Int = 0
func incrementBy(amount : Int, numberOfTimes times : Int){
count += amount * times
print(count)
}
}
下面看输出结果
14
这里可见:
- 这里
times
就是给numberOfTimes
起的别名。
还需要说明的是,在操作可选值的时候,在操作之前加上?
,如果?
之前是nil
,?
后面的东西都会被忽略,并且整个表达式会返回nil
,否则,?
之后的东西都会被运行,在这两种情况下,整个表达式的值是一个可选值。
下面我们看一下代码。
let optionalSquare : Square? = Square(sideLength : 2.5, name : "optional square")
let sideLength = optionalSquare. sideLength
后记
已经很晚了,今天就写这么多吧,未完,待续~~~