有来写学习swift的笔记了。。。。
函数的默认值
func sum3(x: Int = 1, y: Int = 2) -> Int {
return x + y;
}
print(sum3()) // 3
//print(sum(x: 10)) // 以前的版本,现在不能用了
没有返回值的函数
//MARK: 函数无返回值, 用于闭包时
/*
1.直接省略
2.()
3. Void
*/
func demo1() {
print("哈哈")
}
func demo2()-> () {
print("hehe")
}
func demo3() -> Void {
print("嘻嘻")
}
使用常量记录函数
func sum(x: Int, y: Int) -> Int {
return x + y
}
// 1>定义一个常量记录函数
let f = sum // f的格式 (Int, Int) -> Int
// 2>在需要的时候执行
print(f(20, 40)) // 60
//f(<#T##Int#>, <#T##Int#>) sum(x: <#T##Int#>, y: <#T##Int#>) 这两个调用是这样的
闭包
在OC中block是匿名的函数
在swift中函数是特殊的闭包
闭包:
- 提前准备好代码
- 在需要的时候执行
- 可以当做参数传递
闭包的应用场景:
- 异步执行完成回调
- 控制器间回调
- 自定义视图回调
回调特点:
- 以参数回调处理结果
- 返回值为Void
// 1>最简单的闭包
let b1 = { // b1 的类型 () -> () 没有参数没有返回值的函数 如果没哟参数,没有返回值,可以省略, 连 in 都一起省略
print("hello")
}
// 执行闭包
b1() // hello
// 最简单的 block
void(^b1)() = ^{
NSLog(@"Hello");
};
b1();
// 2>带参数的闭包
// 闭包中, 参数、返回值、实现代码 都是写在{}中
// 使用关键字 in 分隔定义和实现
// {形参列表 -> 返回值类型 // 实现代码 }
let b2 = { (x: Int) -> () in
print(x)
}
b2(3) // 3
// 3>带参数/ 返回值的闭包
let b3 = {
(x: Int) -> Int in
return x + 250
}
print(b3(111)); // 361
// 示例
func loadData(completion:@escaping (_ result:[String])->()) -> () {
// GCD: 将任务添加到队列,指定执行任务的函数
// ‘队列’调度任务(block/闭包), 以同步/异步的方式执行
// 在异步执行任务,获取结果,通过block/闭包 回调
DispatchQueue.global().async {
print("耗时操作 \(Thread.current)") // 耗时操作 <NSThread: 0x600000071900>{number = 3, name = (null)}
// 休眠
Thread.sleep(forTimeInterval: 1.0)
//获得结果
let json = ["头条", "八卦", "粗大事了"]
// 主队列回调
DispatchQueue.main.async(execute: {
print("主线程更新 UI \(Thread.current)") // 主线程更新 UI <NSThread: 0x600000067300>{number = 1, name = main}
//回调 ->执行 闭包(通过参数传递的)
completion(json)
})
}
}
//在另外一个方法里调用
// 尾随闭包
loadData { (result) in
print("获取的新数据 \(result)") // 获取的新数据 ["头条", "八卦", "粗大事了"]
}
// ‘尾’随闭包
// 如果函数的最后一个参数是闭包, 函数参数可以提前结束,最后一个参数直接使用{}包装闭包的代码。
// 嵌套的GCD闭包,系统不会把里面的尾随闭包自动处理,可以自己处理
//按函数本身编写的结果
loadData(completion: {
(result) -> () in
print(result)
})
{}的坑
let l = UILabel()
//(l) 参数结束{尾随闭包}
view.addSubview(l)
//报错: Extra argument in call
// 调用了额外的参数 {}是闭包
{
let l = UILabel()
view.addSubview(l)
}
闭包的循环引用
class ViewController: UIViewController {
var completionCallBack:(()->())? // 定义一个属性
override func viewDidLoad() {
super.viewDidLoad()
// 闭包对self进行了copy, 闭包执行完以后, 会自动销毁, 同时释放self的引用
// 使用weakSelf打破循环引用
weak var weakSelf = self // 只能用var修饰
// weak 可能会在运行时被修改 -> 指向的对象一旦被释放,会自动设置为 nil
loadData {
// 解包两种方式
// ? 可选解包 如果self已经被释放,不会项对象发送view的消息,更安全合理
// ! 强制解包 如果self已经被释放,强行解包会崩溃
/*
weakSelf.view - 只是单纯的发送消息, 没有计算
强行解包,因为需要计算,可选项不能直接参与运算
*/
print(weakSelf?.view ?? "")
}
// 方法二:swift推荐方法
// [weak self] 表示 {}中所有self 都是弱引用, 需要注意解包
loadData { [weak self] in
print(self?.view ?? "")
}
// 方法三:
// [weak self] 表示 {}中所有self 都是assign的,不会强引用,但是,如果对象释放,指针地址不会变化
// 如果对象被释放,继续调用,就会出现野指针的问题
loadData { [unowned self] in
print(self.view)
}
}
func loadData(completion:@escaping () -> ()) -> (){
// 使用属性记录闭包 -> self对闭包引用了
// 循环引用了
completionCallBack = completion
DispatchQueue.global().async {
print("耗时操作")
DispatchQueue.main.async{
// 回调, 执行闭包
}
}
}
deinit {
print("over")
}
}
oc中解决循环引用的两种方法
__weak typeof (self) weakSelf = self;
[self loadData:^{
NSLog(@"%@", weakSelf.view);
}];
/*
__unsafe_unretained 同样是assign的引用(MRC 中没有 weak)
在MRC中如果弱引用队形都是使用assign ,不会增加引用计数,但是一旦对象被销毁,地址不会改变,继续访问,会出现野指针错误
在 ARC weak本质上是一个观察者模式,一旦发现对象不释放,会自动将地址设置为nil, 更加安全
*/
__unsafe_unretained typeof (self) weakSelf = self;
[self loadData:^{
NSLog(@"%@", weakSelf.view);
}];
网友评论