Swift-方法(Methods)
Posted 人散风中
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift-方法(Methods)相关的知识,希望对你有一定的参考价值。
前言
方法即是函数。结构体和枚举能够定义方法是Swift与C/Object-C的主要区别之一。在OC中,类是唯一可以定义方法的类型,而Swift中,结构体、类、枚举内部都可以定义方法。这就牵扯到夲小节所包含的两个知识点:
- 实例方法(Instance Methods)
- 类型方法(Type Methods)
简而言之,实例方法就是我们正常建立的方法,func 关键字修饰,调用的时候先给 结构体/类/枚举 建立一个实例方法,然后使用点语法调用实例方法。而类型方法和OC中的类方法是很相似的(OC中 符号 + 开头的方法都是类方法,通常单例方法都会使用类方法,文章最下面有示例),调用的时候不用实例化 结构体/类/枚举 ,直接用他们的名字点语法类型方法名,两行代码简单直接:
struct SomeStructure
var name = "Tom"
var age = 12
// 实例方法,打印信息
func printInfo()
print(name,age)
// 类型方法,至于为啥用static,下面介绍
static func counterSomeThing()
print("------类型方法")
// 调用类型方法,直接结构体名字即可
SomeStructure.counterSomeThing()
// 调用实例方法,先创建一个结构体的实例方法
let instanceMethod = SomeStructure()
// 使用点语法调用
instanceMethod.printInfo()
分条详述
实例方法
其实通过前言中的代码段,已经很明确的说明什么是实例方法了,这里只要说一下实例方法的一些特性和注意点。实例方法要卸载它所属类型的大括号内,并且只能被它所属类型的某个实例方法调用,如上面实例代码,必须先建立所属类型的实例方法才能调用类型内部的实例方法。示例代码中对一个数字进行处理,管中窥豹,简单再体验下实例方法:
class HandleDigit var dight = 0 // 自增 func increase() dight += 1 // 加上某个数 func addDight(addNumber number: Int) dight += number // 重置 func resetDight() dight = 0 var hander = HandleDigit() // 调用实例方法 hander.increase() // digit = 1 hander.addDight(addNumber: 100) // digit = 101 hander.resetDight() // digit = 0
关于方法的局部名称和外部参数名称,在前面学习的 函数小节的 函数参数名称 中有详细的介绍,包括默认第一个参数名称省略、自定义参数的描述等。其实方法、函数的本就是一个概念,如果对于书写方法有比较好的体会,那么在日常的编码中也会使自己的代码更具可读性。
关于self属性,这个也是Swift和OC的主要区别之一。类型的每一个实例都有一个隐含的属性叫做self,self完全等同于该实例本身。实际上,平常写代码的时候,我们基本极少使用self,目前我接触到的基本知识中,只有在闭包中调用外部的属性或方法时,必须要使用self,其他时间基本没用过。教材中还有一种情况需要使用self,那就是局部变量和全局变量名字完全一样时,用self.属性名,会默认调用全局的那个属性。不过,这么坑爹的命名方法,真的有这么写的么 ㄟ(▔ ,▔)ㄏ ,看看代码这种命名方式吧:
// 当全局属性和局部属性出现命名完全一样时,使用self加以区分。 class MakeName let firstString = "Hello" func printIntro() let firstString = "World" print(firstString,self.firstString) let name = MakeName() name.printIntro() // 输出 World Hello
不知道注意了没,上面一直使用的类写的实例代码,而没有使用结构体和枚举,其实,真的不一样。。。已经说过,类是引用类型,尔机构体和枚举是值类型。一般情况下,值类型的属性是不能在它的实例方法中被修改的。但是,如果确实需要在结构体或者枚举的实例方法中修改内部属性值,那么可以选择 变异(mutating) 这个方法,然后就可以在实例方法中修改内部属性值了。这个修改并不是值拷贝,而是在原有的基础上修改数据。下面的示例代码中可以看出来这一点。
要使用变异方法,将关键字 mutating 放到方法的关键字 func 之前就可以了:// 枚举、结构体修改内部属性值,以结构体为例 struct ModifyProperties var x = 0.0, y = 0.0 mutating func movePoint(xChange changeX: Double, yChange changeY: Double) x += changeX y += changeY // 实例并初始化 var originalPoint = ModifyProperties(x: 2, y: 2) // 修改 originalPoint.movePoint(xChange: 33, yChange: 66) // 查看现在 ModifyProperties 的属性值 originalPoint.x // 35 originalPoint.y // 68
因为要修改结构体或者枚举内部属性值,并且结构体和枚举都是值类型,所以不能把结构体或者枚举设置为常量的实例方法,即不能用 let 修饰。否则会直接抛出错误。
在可变方法中,可以给self,即类型本身赋值,这个以后会在枚举中经常用到。这次不用结构体做例子了,直接看枚举的用法吧,毕竟比结构体稍微复杂些:
enum Volume // 音量,低、正常、高 case Low, Normal, Height // 修改自身值 mutating func nextState() switch self case .Low: self = .Normal case .Normal: self = .Height case .Height: self = .Low // 调用 var volume = Volume.Low // volume = Low volume.nextState() // volume = Normal volume.nextState() // volume = Height
类型方法
就是前言中那种简单地调用方式,教材中提供了一个挺长的示例代码,不过个人感觉并没有解释我想知道的:其实我最想知道的是什么时间用类型方法,什么时间用实例方法,是否和OC中的相似。这个相信会在以后的使用、学习中,慢慢了解的。刚才本来想Google下的,结果翻墙工具不好使了,访问不了,百度了下,也没太好的结果,有个博客把教材中的例子完全复制了,并且页面看起来很赏心悦目,可以去看看,点击查看 。下面我就用几行代码展示类型方法的基本使用吧。
声明结构体和枚举的类型方法,在方法的func关键字前加上关键字static。类有些不同,类可能使用关键字来允许子类重写父类的实现方法。class SomeTypeClass static var number = 0 // 类有两种类型方法的定义样式,枚举和结构体只有关键字 static一种方式 // 使用关键字 class class func counter() number += 3 // 使用关键字 static static func printDescrible() print(number) // 调用类型方法 SomeTypeClass.number // number = 0 SomeTypeClass.counter() // number = 3 SomeTypeClass.printDescrible()
如何线程安全的建立一个单例
其实这个算是自己临时加的一个东西,毕竟这东西天天都在用,然而一段时间不写后,还是有点生僻的。先写个OC版的吧:// 线程安全创建单例 + (ColorManager *)shareColorManger static ColorManager *shareColorManagerInstance = nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^ shareColorManagerInstance = [[self alloc]init]; ); return shareColorManagerInstance;
当项目中需要多次用到单例模式的时候,显然把单例模式的定义设置成一个宏定义,用的时候肯定会方便很多。这篇文章 详细的介绍了如何宏定义一个单例模式。因为符号 # 的问题,没法在这里看到示例代码了。其实Swift版的单例模式也是一样的吧……然而并不一样,这篇博客详细分析了从OC过渡到Swift的单例写法到最终的安全优美的Swift单例写法 ,博主真大神,涨了不少见识,最终的单例就是下面这种写法:
// Swift单例模式 class Singleton static let shareInstance = Singleton() private init() // 这样就阻止了其他对象使用这个类的默认 “()” 初始化方法
结束语
随手一翻,就能找到一张有意思的壁纸。。。睡觉睡觉,瞌睡死了。
以上是关于Swift-方法(Methods)的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中结束 CAEmitterLayer 的正确方法是啥?