Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Swift| 基础语法(四)

Swift| 基础语法(四)

作者头像
進无尽
发布于 2018-09-12 09:34:44
发布于 2018-09-12 09:34:44
1.5K00
代码可运行
举报
文章被收录于专栏:進无尽的文章進无尽的文章
运行总次数:0
代码可运行

前言

总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多篇来展示,希望对大家学习swift有所帮助,同时也是对自己的一个总结。

Swift| 基础语法(一)

Swift| 基础语法(二)

Swift| 基础语法(三)

Swift| 基础语法(四)

Swift| 基础语法(五)

本文涉及:

  • 闭包
  • 代理
  • 通知
  • 构造函数
  • 懒加载
  • 重写属性的Set、get发方法

一、闭包

Swift 中闭包的概念就像是Objective-C中的block。OC中的block类似于匿名函数,闭包是用来定义函数, 同时闭包可以嵌套和作为参数传递。 在 Swift 中,函数也只不过是一种特殊的闭包。

Swift 中的闭包有很多优化的地方:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1 根据上下文推断参数和返回值的类型
2 从单行表达式闭包中隐式返回 可以省略return
3 可以使用简化的参数如 $0 $1 意为从0或者1开始
4 提供了尾随闭包的语法

//语法   parameters参数 return 隐藏了
//{(parameters) -> return type in
//    parameters
//}

各种格式下的闭包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//最简单的闭包//省略in的
let b = {
    print("这也是闭包")
}
b() //执行

//有参数和返回值的闭包
let countNum = {(num1:Int,num2:Int)->Int in
    return num1+num2;
}
let count1 = self.countNum(2,3)
print("count1: \(count1)")

// 有参数无返回值的闭包
let countNum = {(num1:Int,num2:Int)-> () in
        let aa  = num1+num2;
        print("count2: \(aa)")
}
countNum(222,333)

//没有参数有返回值的闭包 
let countNum11 = {()-> Int in 
        self.global = 800
        return self.global!;
}
let newValue = countNum11()
print("count3: \(newValue)")

闭包的调用都带有 ()//这个表示执行

@noescape 和 @escaping

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
简单的介绍就是如果这个闭包是在这个函数结束前内被调用,就是非逃逸的即noescape。
如果这个闭包是在函数执行完后才被调用,调用的地方超过了这函数的范围,所以叫逃逸闭包。

举个例子
就是我们常用的masonry或者snapkit的添加约束的方法就是非逃逸的。因为这闭包马上就执行了。
网络请求请求结束后的回调的闭包则是逃逸的,因为发起请求后过了一段时间后这个闭包才执行。
比如这个Alamofire里的处理返回json的completionHandler闭包,就是逃逸的。

loadData { (result) in
        print("获取json信息\(result)")
    }
func loadData(completion:  @escaping (_ result: [String])->()) -> () {
    DispatchQueue.global().async {
        print("耗时操作\(Thread.current)")
        Thread.sleep(forTimeInterval: 1.0);
        let json=["12","23","34"]
        DispatchQueue.main.async(execute: {
            print("主线程\(Thread.current)")
            completion(json)
        })
    }
}

定义闭包属性的问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
在Swift中,如果在某个类中定义一个属性,那么这个属性必须要初始化,否者会报错,
如果暂时不想初始化,那么可以在后面写上一个 ? 号

但是在定义闭包的属性时,一定要注意,以下这种写法是最常见的一种错误写法:
  /** 当前写法代表闭包的返回值可以是nil,而不是初始化的闭包 */
  var finished: () -> ()?
  /** 正确写法:需要在整个闭包的后面加问号 */
  var finished: (() -> ())?

闭包的循环引用问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
在Swift开发中,有一个原则就是能不写self就不写self,但是在闭包中必须写上self;
这是因为闭包是用来保存一段代码,而且系统也不知道这段代码具体的调用时间,
所以为了保证闭包中的对象不被释放,需要 self 进行一次强引用;这其实和Block中的原理差不多。

所以以后看到self基本上都和闭包有关系。(这也是闭包中循环引用来源的原因)

下面我举一个简单的关于闭包循环引用的例子:

你定义了两个控制器:OneController和TwoController,OneController只是负责push出TwoController,
我们在TwoController中进行一些关于闭包的操作,然后在pop返回的时候查看该控制器是否被销毁了,
来验证闭包是否发生了循环引用问题;
在TwoController中我们只需要简单写一些代码即可:

 // 定义一个闭包的属性 
 var finished: (() -> ())?
 // 定义一个函数,参数为闭包
 func loadData(finished: () -> ()) {
    print("调用了")
    self.finished = finished
    finished();
}
// 函数调用
loadData { () -> () in
        print("回调了")
        // 这句又强引用self,导致循环引用
        self.view.backgroundColor = UIColor.redColor()
    }
// 判断是否被销毁了
deinit {
       print("控制器被销毁了")
}

当我们执行以上代码,并且从TwoController返回到OneController时,
TwoController的deinit方法没有被调用,表明TwoController没有被销毁,闭包存在了循环引用的问题;

这是因为:控制器通过闭包属性引用闭包,而闭包中又强引用着self(控制器),所以导致了循环引用的问题;

Swift中关于循环引用的解决方案
weak var weakSelf = self
那么原先代码中只需要把self改成weakSelf即可
// 由于weakSelf为可选类型,这里必须保证有值,所以加上!号
weakSelf!.view.backgroundColor = UIColor.redColor()

二、代理

流程基本和OC中的一致

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import UIKit
@objc protocol mydelegate {
    func FF1(a:String)     //必须实现的
   @objc optional func FF2(aa:String)  //可以选择是否实现的
}

/*在声明的protocol中为什么要用  @objc 呢? 
因为 Swift 的 protocol 是可以除了 class 以外的其他类型遵守的,而对于像 struct 或是 enum 这样的类型,
本身就不通过引用计数来管理内存,所以也不可能用 weak 这样的 ARC 的概念来进行修饰。
想要在 Swift 中使用 weak delegate,我们就需要将 protocol 限制在 class 内。
一种做法是将 protocol 声明为 Objective-C 的,这可以通过在 protocol 前面加上 @objc 关键字来达到*/

class MyTest: NSObject {
    weak var delegate:mydelegate?
    /*一定要 weak var  delegate: AADelegate?  去声明你的代理属性,避免循环引用问题*/
    func test() -> () {
        self.delegate? .FF1(a: "代理方法1")
         /* 为什么要 delegateOK.clickAction?() 中要有个问号呢
            原因是在OC的代码中, 用respondsToSelector()方法来判断是否实现了方法。
            而在swift 中就直接可以用 ? 来判断是否实现了方法。有时系统可能会给你自动提示,然后你就fix 一下*/
    } 
}

/*遵循协议*/
class ViewController: UIViewController,mydelegate {
override func viewDidLoad() {
    super.viewDidLoad()

    let myTest = MyTest()
    myTest.delegate = self
    myTest.test()  
  }
  
   /*实现代理方法 */
   func FF1(a:String){
      print("代理:\(a)")
  }
}
  代理:代理方法1

三、通知

流程基本和OC中的一致

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyTest: NSObject {        
    func test() -> () {
        NotificationCenter.default.post(name: NSNotification.Name.init("test"), object: self, userInfo: ["post":"哈哈"])
    }
    
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    NotificationCenter.default.addObserver(self, selector: #selector(test), name: NSNotification.Name.init("test"), object: nil)
   
    let myste = MyTest()
    myste .test()
}
@objc func test(nofi : Notification) -> Void {
    let str = nofi.userInfo!["post"]
    let str1 = str as! String
    print("通知传来了: \(str1)")
}
deinit {
    NotificationCenter.default.removeObserver(self)
}

四、构造函数

普通构造函数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//构造方法
init(name: String, age: Int) {
    //当属性名和参数名相同时  需要加上 self来区分
    self.name = name
    self.age = age
    super.init()
}

let myste = MyTest.init(name: "bady", age: 19)
构造函数-KVC构造
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @objc var name: String?
 @objc var age: Int = 0

 //构造方法
init(dict: [String : AnyObject]){
    super.init()
    setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forKey key: String) {
    super.setValue(value, forKey: key)
}
//过滤掉 不存的在属性对应的key
override func setValue(_ value: Any?, forUndefinedKey key: String) {
    print("no: \(value),\(key)")
}

 let dic = ["name":"zhangsan","age":2,"title":"nini"] as [String : Any]
 let myste = MyTest.init(dict: dic as [String : AnyObject])
 print("name: \(myste.name)\n age:\(myste.age)")

在swift 4.0中使用系统方法setValuesForKeys()进行赋值,明明有这个属性,但它还是走

override func setValue(_ value: Any?, forUndefinedKey key: String)

这个未定义的方法

原因是:swift 4.0 版本要在属性前面加@objc

五、懒加载

格式:

lazy var 变量: 类型 = { 创建变量代码 }()

懒加载的写法本质上是定义并执行一个闭包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//MARK: -View懒加载
lazy var View: UIView = {
    let view = UIView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
    view.backgroundColor = UIColor.redColor()
    return view
}()

//MARK: -TableView懒加载
lazy var zyTableView: UITableView = {
    let tempTableView = UITableView (frame: self.view.bounds, style: UITableViewStyle.plain)
    tempTableView.delegate = self
    tempTableView.dataSource = self
    return tempTableView
}()

  //MARK: -数组懒加载
lazy var dataList: [String] = {
        print("我懒加载了")
        return ["lnj", "lmj", "why"]
  }()

六、重写属性的Set、get发方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyTest: NSObject {

  //定义一个变量
  private var _tittle: String?
  var tittle: String?{
      set{
          print("重写了set方法!")
          _tittle=newValue
      }
      get{
          return _tittle
      }
   }
}

myste.tittle = "asd"
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.05.16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
14.闭包
闭包引入 计算1个数的平方 函数写法 func square(param:Int) -> Int{ return param * param } square(param:3) 闭包写法 let squareCloure = { (param:Int) -> Int in return param * param } squareCloure(3) 闭包含义 闭包是可以被传递和引用的一个独立模块 闭包能够捕获和存储定义在其上下文中的任何常量和变量,即闭合并包裹那些常量和变量,因此被称为
YungFan
2018/10/11
8210
Swift基础语法(四)
在Swift5之前,我们一般是采用上面的方式来处理异常,在Swift5之后,苹果推出了一个Result枚举,Result枚举可以更加优雅地去处理异常。
拉维
2020/07/06
4.1K0
Swift基础语法(四)
swift4.0语法杂记(精简版)
一、swift简史 1、介绍 swift是苹果公司于2014年推出用于撰写OS和iOS应用程序的语言。它由苹果开发者工具部门总监“克里斯.拉特纳”在2010年开始着手设计,历时一年完成基本的架构。到后来苹果公司大力投入swift语言的研发,于2014年发布这一语言的第一版本。swift2.0之后的语法则趋于稳定,2017年发布的swift4.0虽有改动,但也只是增添了一些新特性。这些新特性需要在Xcode9上运行才能显示出效果。值得一提的是它支持unicode9,也就是说,可以用某些图片图标来充当变量。
谦谦君子修罗刀
2018/05/02
15.7K0
swift4.0语法杂记(精简版)
Swift基础语法简化版(续)
闭包能够捕获和存储定义在其上下文中的任何常量和变量,即闭合并包裹那些常量和变量,因此被称为“闭包”。
拉维
2020/06/23
1.6K0
iOS循环引用
iOS循环引用 当前类的闭包/Block属性,用到了当前类,就会造成循环引用 此闭包/Block应该是当前类的属性,我们经常对Block进行copy,copy到堆中,以便后用。 单方向引用是不会产生循环引用。需要self引用闭包/Block,Block中使用self。 有两个规则: 如果你是通过引用来访问一个实例变量,那么将强引用至self。 如果你是通过值来访问一个实例变量,那么将直接强引用至这个“值”变量。 Object-C Block循环引用情况 一般来说我们总会在设置Block之后,在合适的时间
用户1941540
2018/05/11
8300
Swift基础语法(二)
我们之前介绍的数组Array、字典Dictionary等,都是值类型,而函数是引用类型。
拉维
2020/06/02
2.3K0
Swift基础语法(三)
chineseScore和mathScore也是存储属性,用来记录该学生的语文分数和数学分数。
拉维
2020/06/23
2.1K0
Swift基础语法(三)
Swift| 基础语法(三)
总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多篇来展示,希望对大家学习swift有所帮助,同时也是对自己的一个总结。
進无尽
2018/09/12
1.6K0
Swift| 基础语法(三)
iOS面试题-Swift篇
面试题持续整理更新中,如果你正在面试或者想一起进阶,不妨添加一下交流群 1012951431一起交流。
会写bug的程序员
2020/06/28
3.8K0
iOS面试题-Swift篇
Swift学习总结
5、switch语法与objc差别很大,执行一个分支马上停止,不需要break语句跳出,反而想要穿透到下面分支还要用fallthrough语句。
SheltonWan
2019/06/06
3.2K0
Swift学习总结
Swift| 基础语法(二)
总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多篇来展示,希望对大家学习swift有所帮助,同时也是对自己的一个总结。
進无尽
2018/09/12
8100
Swift| 基础语法(五)
总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多篇来展示,希望对大家学习swift有所帮助,同时也是对自己的一个总结。
進无尽
2018/09/12
2.3K0
Swift| 基础语法(五)
使用 Swift 提高代码质量
京喜APP最早在2019年引入了Swift,使用Swift完成了第一个订单模块的开发。之后一年多我们持续在团队/公司内部推广和普及Swift,目前Swift已经支撑了70%+以上的业务。通过使用Swift提高了团队内同学的开发效率,同时也带来了质量的提升,目前来自Swift的Crash的占比不到1%。在这过程中不断的学习/实践,团队内的Code Review,也对如何使用Swift来提高代码质量有更深的理解。
Swift社区
2021/11/26
4.8K0
使用 Swift 提高代码质量
25.Swift学习之@objc
在 Swift 中很多地方都是用到了一个修饰符@objc,尤其是在混编项目中,出于安全的考虑,可以将需要暴露给 Objective-C 使用的如类,属性和方法的声明前面加上 @objc。那么在 Swift 中哪些地方用到了这个关键字呢?
YungFan
2018/12/19
1.4K0
Swift开发规范-修订版
《Swift开发规范》发布之后得到了很多Swifter的关注,很多读者提议最好为每条规约添加一些代码示例,其实在发布之前,我就考虑到要加代码示例这件事,但是后来还是因为偷懒没加。最近利用了空余时间,对之前的版本进行了完善,加入了代码示例及编译效率规约等等,并且考虑到读者对某些规约有些疑惑,也为部分规约增加了说明,推出新的版本--《Swift开发规范-修订版》。
CoderStar
2022/08/24
1.8K0
46 道 Swift 常见面试题解
3、Set 独有的方法有哪些? 4、实现一个 min 函数,返回两个元素较小的元素 5、map、filter、reduce 的作用 6、map 与 flatmap 的区别 7、什么是 copy on write 8、如何获取当前代码的函数名和行号 9、如何声明一个只能被类 conform 的 protocol 10、guard 使用场景 11、defer 使用场景 12、String 与 NSString 的关系与区别 13、怎么获取一个 String 的长度 14、如何截取 String 的某段字符串 15、throws 和 rethrows 的用法与作用 16、try?和 try!是什么意思 17、associatedtype 的作用 18、什么时候使用 final 19、public 和 open 的区别 20、声明一个只有一个参数没有返回值闭包的别名
Swift社区
2021/11/26
5.5K0
iOS block探究(一): 基础详解你要知道的block都在这里
你要知道的block都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文大纲 block基础语法 block基础使用 block常见问题 block进阶: 深入代码理解 block基础语法 block作为C语言的扩展,正在OC中发挥着举足轻重的作用,我们经常使用block块作为回调函数,这样做可以大大简化编程方式,多线程的核心也是block,因此,学会使用block并深入理解block有助于我们写出更好的代码。 block基础知识
WWWWDotPNG
2018/04/10
9320
Swift: 为什么要避免在结构体中使用闭包?
闭包可以简化iOS开发人员的工作。好吧,如果这使我们工作变得容易,那为什么我要避免在Swift结构中使用闭包呢? 原因是:内存泄漏和意外行为。
韦弦zhy
2020/03/20
1.8K0
Swift: 为什么要避免在结构体中使用闭包?
swift 自动引用计数
1、每创建一个类的实例对象,ARC就会分配一块内存来存储实例信息(实例的类型信息及实例的存储属性) 2、当实例不再被使用时,ARC 释放实例所占用的内存,这确保了不再被使用的实例,不会一直占用内存空间 3、当 ARC 释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃 4、为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为1,ARC都不会销毁这个实例
xy_ss
2023/11/22
2010
swift 自动引用计数
Swift-MVVM 简单演练(一)
Swift-MVVM 简单演练(二) Swift-MVVM 简单演练(三) Swift-MVVM 简单演练(四) 前言 最近在学习swift和MVVM架构模式,目的只是将自己的学习笔记记录下来,方便自己日后查找,仅此而已!!! 本来打算一篇全部搞定的,但是简书每篇文章只能写大约不超过15000字的内容,因此只能分开写了。 如果有任何问题,欢迎和我一起讨论。当然如果有什么存在的问题,欢迎批评指正,我会积极改造的! ---- 这篇文章都写啥 自定义NavgationBar 抽取便利构造函数 初步的下拉刷新/上
用户1890628
2018/05/10
10.6K0
相关推荐
14.闭包
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验