1、协议的基本使用
- 协议可以继承
- 类、结构体和枚举都可以遵循协议
- 如果遵循了协议,则必须实现协议里所有的方法
2、协议的代理使用
轻量级的时候只需加class
protocol Work: class {
func work()
}
class Person {
//只有Work继承于work或者NSObjectProtocol,这里才能用weak
weak var delegate: Work?
func doWork() {
// 让别人"打印机" 去打印
delegate?.work()
}
}
更全的时候加NSObjectProtocol
protocol Work: NSObjectProtocol {
func work()
}
class ColorP: NSObject, Work {
func work() {
print("彩色打印机打印")
}
}
3、让协议的方法可选(不用实现)
纯Swift并不提倡这么做,从契约精神上讲遵循协议就应该全部做到里面规定的内容
@objc
protocol Work {
@objc optional func test()
}
//下面是关键字objc的另一个使用场景
class pp:NSObject{
func test(a: Int) {
}
@objc(xxx:)//告诉oc,当在oc里使用时下列方法名为xxx:
func test(a: Double) {
}
}
4、泛型
定义:不是某一种具体的类型,它的类型在传值的时候才会决定
// 函数
func exchange(num1: inout T, num2: inout T) {
let temp = num1
num1 = num2
num2 = temp
}
var num1 = "10"
var num2 = "20"
//exchange(num1: &num1, num2: &num2)
exchange(num1: &num1, num2: &num2)
num1
num2
// 结构体
struct Point {
var x: T
var y: T
}
let p = Point(x: 10, y: 10)
p.x
let p2 = Point(x: 10.1, y: 10.3)
p2.x
// 类
class Stack {
var nums: [T] = []
func push(num: T) {
nums.append(num)
}
func pop() -> T {
return nums.removeLast()
}
}
let st = Stack()
st.push(num: "10")
st.push(num: "20")
st.nums
st.pop()
st.pop()
//协议
protocol Some {
// 协议里面,定义一个泛型, associatedtype
associatedtype T
func work() -> T
func eat() -> T
}
class Person: Some {
func work() -> Person {
print("人工作")
return self
}
func eat() -> Person {
print("人吃饭")
return self
}
}
let p22 = Person()
p22.work().eat().work().eat().eat().eat().eat()
class Dog: Some {
func work() -> Dog {
print("工作")
return self
}
func eat() -> Dog {
print("吃饭")
return self
}
}
let d = Dog()
d.eat().work().eat().eat().eat().eat()
class Stu : Person {
}
func test2(a: T) where T: Person {
}
test2(a: Person())
用where给泛型加限制条件
func test2(a: T) where T: Person {
//这里的意思是泛型T必须是继承于Person类型
}
5、闭包的基本使用
var addBlock: (Int, Int) -> (Int) = {
(a:Int,b:Int) -> (Int) in
return a + b
}
addBlock(12, 12)
如果闭包参数是空,可以省略in和in前面的内容
var simpleBibao: () -> (Int) = {
print("test")
return 10
}
6、三种闭包
- 参数闭包
- 尾随闭包:当设计一个函数,其内部需要接收闭包,一定要注意尽量把闭包类型的参数放最后
- 逃逸闭包:如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”的闭包(闭包,生命周期,是函数)
7、闭包循环的问题
OC中的循环问题
定义block的时候,用setXXBlock能比较方便的打出格式
- __weak和__unsafe_unretained的区别:前者释放后会置为nil而后者不会
- __strong的使用:当一个Ablock里面嵌套另一个耗时操作的Bblock,在Bblock里需要使用self,为了防止使用时self已经被释放为空的情况,这时候会使用关键字__strong
__weak typeof(self)weakSelf = self; [self setBlock:^(int a) { // __strong typeof(self)strongSelf = weakSelf; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // [strongSelf xxx]; }); }];
Swift中的使用
class Person {
var block: (()->())?
func test() {
block = {
[weak self] in
self
print("test")
}
}
deinit {
print("Person释放了")
}
}
var p: Person? = Person()
p?.test()
p = nil
8、懒加载的使用
使用关键字lazy
class Dog {
var age: Int = 0
}
class Person {
//冒号后面一般跟具体的值、构造函数或者闭包
lazy var name: Dog = {
// () -> Dog in
print("test")
return Dog()
}()
}
注:与OC不同的是Swift中懒加载置为nil以后不能再重复加载了
9、常见注释的写法
另外,Swift里还可以开启注释(让FIXME像感叹号那样有提示便于查找),开启方法:把下面这段代码复制到BuildPhases→NewRunScriptPhases
TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
10、访问权限问题
OC
默认是@protected
OC中通常认为只有成员变量会存在访问权限问题,属性和方法都不存在;成员变量用箭头(->)访问;一旦修饰,该成员变量后面的都被修饰了,之道遇到下一个修饰
Swift
- internal:默认的,类似OC中的protected,当前模块内都可以访问
- private:私有
- fileprivate:在当前源文件中可以访问(当前源文件是指当前这一个xx.swift文件,当前模块是指当前这个Target,Swift中同一个模块不需要import)
-public:修饰的对象可以跨模块,修饰类时不能继承,修饰方法时不能重写 - open:修饰的对象可以跨模块,修饰类时可以继承,修饰方法时可以重写
与OC不同的一个细节是,这些关键字都只会修饰接下来的一个对象,而不是后面所有的
11、异常的抛出和处理
格式与OC类似
// 捕捉, 并且处理
do {
let content = try readFile(path: path)
}catch {
switch error {
case FileError.NoPath:
print("路径不存在")
case FileError.UnAvailable:
print("格式错误")
case FileError.NoContent:
print("没有内容")
default:
print("不知道")
}
}
// try? 处理异常, 就代表, 告诉编译器, 我知道有可能会出现错误, 你帮我自动处理就好, 如果错误, 就直接给我nil < 如果没有错误, 就给我答案
//let content = try? readFile(path: path)
// try!, 代表, 我保证, 绝壁没有任何错误, 告诉编译器, 只负责给我值, 保证是有值得, 放心拿
let content = try! readFile(path: path)
12、Swift调用OC
使用场景:可以调用OC写的三方框架
在Swift项目中创建OC文件时会提示如下图
注:这个桥接文件只对Swift引用OC有效
13、OC调用Swift
OC项目里调用Swift就没这么方便了,这时候同样会出现上图这个窗口,但是不要点Create,我们需要自己去创建(因为Swift文件没有单独的声明和实现文件,且是整个是一个模块)
14、Playground的高级应用
- 资源共享
- 异步执行
- 多页面
- 动画时间轴