当前位置: 首页 > news >正文

swift学习资料2022

  1. String 与 NSString 的关系与区别
    1. Swift的String是struct,而NSString类是NSObject
    2. 什么时候用NSString:​​​​​​​
      1. NSString特有操作和动态特性
      2. NSString有containsString,string只能用rangeOfString
      3. String与Range配合比较麻烦
    3. 什么情况下使用String:​​​​​​​
      1. String更符合字符串“不变”特性,性能提升
      2. String实现了像CollectionType的接口。比如for...in的枚举遍历所有字
  2. Swift字符串的Range截取
    1. let range1:ClosedRange = 1 ... 4
      let range2:CountableClosedRange = 1 ... 4
      let range3:Range = 1 ..< 4
      let range4:CountableRange = 1 ..< 4
              
      let array = ["a", "b", "c", "d", "e", "f"]
      print(array[range1])
      print(array[range2])
      print(array[range3])
      print(array[range4])
  3. throws 和 rethrows 的用法与作用
    1. rethrows:如果一个函数A(例如map)的其中一个参数是一个函数类型B(map的闭包),且B有可能接受throw或不throw的函数,那么A就可以声明为rethrows,这时如果接受的B是不需要的throw的,就不用写do catch来处理错误,如果接受的是throw的才需要。
  4. open与public的区别?
    1. public:可以别任何人访问,但是不可以被其他module复写和继承。
    2. open:可以被任何人访问,可以被继承和复写。
  5. swift中 closure 与OC中block的区别
    1. closure是匿名函数、block是一个结构体对象
    2. block内部会对值类型做一份复制,并不指向之前的值的内存地址,而对于对象类型则会指向对象当前的内存地址,所以修改number时,block里的number数值不变,而修改字符串时,block里的字符串则改变了;closure则默认给外部访问的变量加上了__block修饰词的block。
  6. swift中,如何阻止方法,属性,下标被子类改写?
    1. aaaaaa final 关键字声明类、属性、方法和下标。
      final 声明的类不能被继承,final 声明的属性、方法和下标不能被重写。
      如果只是限制一个方法或属性被重写,只需要在该方法或者属性前加一个 final.
      如果需要限制整个类无法被继承, 那么可以在类名之前加一个final。
  7. associatedtype 的作用
    1. 关联类型: 为协议中的某个类型提供了一个别名,其代表的真实类型在实现者中定义
    2. 泛型(generic)可以使我们在程序代码中定义一些可变的部分,在运行的时候指定。
      使用泛型可以最大限度地重用代码、保护类型的安全以及提高性能。
    3. //协议,使用关联类型
      protocol TableViewCell {
          associatedtype T
          func updateCell(_ data: T)
      }
       
      //遵守TableViewCell
      class MyTableViewCell: UITableViewCell, TableViewCell {
          typealias T = Model
          func updateCell(_ data: Model) {
              // do something ...
          }
      }
  8. try? 和 try!是什么意思​​​​​​​
    1. try?不处理错误,抛出异常函数时, 如果函数抛出异常, 则返回 nil, 否则返回函数返回值的可选值,
    2. try!保证不会出现错误 强制解,抛出异常的时候崩溃, 否则则返会函数返回值
  9. map、filter、reduce 的作用?
    1. [1, 2, 3].map{"\($0)"}// 数字数组转换为字符串数组,["1", "2", "3"]
    2. [1, 2, 3].filter{$0 % 2 == 0} // 筛选偶数,2
    3. [1, 2, 3].reduce(""){$0 + "\($1)"}// 转换为字符串并拼接,"123"
  10. defer、guard的作用?
    1. defer:主要的作用是延迟执行以及在return之前执行。
  11. 如何自定义下标获取
    1. 实现 subscript 即可,索引除了数字之外, 其他类型也是可以的
    2. extension AnyList {
          subscript(index: Int) -> T{
              return self.list[index]
          }
          subscript(indexString: String) -> T?{
              guard let index = Int(indexString) else {
                  return nil
              }
              return self.list[index]
          }
      }
  12. 这段复杂的代码按字母顺序对名称数组进行排序。尽可能简化闭包。
    1. 类型推断系统会自动判断闭包中参数的类型和返回类型,就可以去掉类型:
      
      animals.sort { (one, two) -> Bool in
           return one < two
      }
      可以用$I符号替换参数名:
      
      animals.sort { return $0 < $1 }
      在单语句闭包中,可以省略返回关键字。最后一条语句的值将成为闭包的返回值:
      
      animals.sort { $0 < $1 }
      后,由于Swift知道数组的元素符合equatable,因此可以简单地编写:
      
      animals.sort(by: <)
  13. 什么是可选的,可选可以解决哪些问题?
    1. 使用可选类型(optionals)来处理值可能缺失的情况。在objective-c中,只有在使用nil特殊值的引用类型中才可以表示值缺失。值类型(如int或float)不具有此功能。
      Swift将缺乏值概念扩展到引用类型和值类型。可选变量可以包含值或零,表示是否缺少值。
  14. 构体和类之间的主要区别。
    1. 类支持继承;结构不支持。
      类是引用类型;结构体是值类型。
  15. 什么是泛型(通用类型)?它们解决了什么问题?
    1. 提高代码的复用性。
    2. 在swift中,可以在函数和数据类型中使用泛型,例如在类、结构体或枚举中。
      泛型解决了代码重复的问题。当有一个方法接受一种类型的参数时,通常会复制它以适应不同类型的参数。
      例如,在下面的代码中,第二个函数是第一个函数的“克隆”,但它接受字符串而不是整数。
    3. func areIntEqual(_ x: Int, _ y: Int) -> Bool {
        return x == y
      }
      
      func areStringsEqual(_ x: String, _ y: String) -> Bool {
        return x == y
      }
      
      areStringsEqual("ray", "ray") // true
      areIntEqual(1, 1) // true
      通过采用泛型,可以将这两个函数合并为一个函数,同时保持类型安全。下面是通用实现:
      
      func areTheyEqual<T: Equatable>(_ x: T, _ y: T) -> Bool {
        return x == y
      }
      
      areTheyEqual("ray", "ray")
      areTheyEqual(1, 1)
      由于在本例中测试的是相等性,所以将参数限制为遵守 Equatable 协议的任何类型。此代码实现了预期的结果,并防止传递不同类型的参数。
  16. nil 和 .none有什么区别?
    1. 没有区别,none == nil
  17. Swift和OC的区别?
    1. swift是静态语言,有类型推断,OC是动态语言。
    2. swift面向协议编程,OC面向对象编程
    3. swift注重值类型,OC注重引用类型。
    4. swift支持泛型,OC只支持轻量泛型
    5. swift支持静态派发(效率高)、动态派发(函数表派发、消息派发)方式,OC支持动态派发(消息派发)方式。
    6. swift支持函数式编程
    7. swift的协议不仅可以被类实现,也可以被struct和enum实现
    8. swift有元组类型、支持运算符重载
    9. swift支持命名空间
    10. swift支持默认参数
    11. swift比oc代码更加简洁
    12. swift语法简单易读、代码更少,更加清晰、易于维护
    13. 更加安全,optional的使用更加考验 程序员 对代码安全的掌控
    14. 泛型、结构体、枚举都很强大
    15. 函数为一等公民,便捷的函数式编程
    16. 有命名空间 基于module
    17. 类型判断
  18. swift的派发机制
    1. 三种派发机制:直接派发, 函数表派发 和 消息机制派发
      1. 直接派发 :最快指令集更少, 编译器有很大的优化空间, 例如函数内联等,但缺乏动态性,没继承,静态调用。
      2. 函数表派发:使用了一个数组存储类声明和函数指针. 称为虚函数表。查表比直接派发慢. 从字节码角度看, 多两次读和一次跳转的损耗. 另一个慢在于编译器无法优化.这种基于数组, 缺陷在于无法拓展. 子类会在最后插入新的函数, 没有位置可以让 extension 安全地插入函数.
      3. 消息机制派发:是oc的消息转发机制,是最动态的方式. 效率最低,但是缓存后跟函数表派发一样快
    2. Swift 的派发机制:使用 dynamic 修饰的时候会通过 Objective-C 的运行时进行消息机制派发.总结起来有这么几点:
      1. 值类型、协议和类的extension总是会使用直接派发
      2. NSObject 声明作用域里的函数都会使用函数表进行派发.
      3. 协议里声明的, 并且带有默认实现的函数会使用函数表进行派发.
      4. NSObject 的 extension 会使用消息机制进行派发
    3. 指定派发方式 
      1. 直接派发:final、static、@inline
      2. 消息派发:dynamic、@objc
  19. Struct和Class区别
    1. Struct不支持继承、Class支持继承
    2. Struct是值类型,Class是引用类型
    3. Struct无法修改自身属性值,函数需要添加mutating关键字
    4. Struct初始化方法是基于属性的
    5. Struct不需要deinit方法,因为值类型不关心引用计数,Class需要deinit方法。
  20. swift中mutating的作用?
    1. swift中协议是可以被Struct和enum实现的,mutating关键字是为了能在被修饰的函数中修改struct或enum的变量值。对Class完全透明。
  21. associatedtype 的作用?
    1. 简单来说就是 protocol 使用的泛型
    2. protocol ListProtcol {
          associatedtype Element
          func push(_ element:Element)
          func pop(_ element:Element) -> Element?
      }
    3. 实现协议的时候, 可以使用 typealias 指定为特定的类型, 也可以自动推断, 如​​​​​​​​​​
    4. class IntList: ListProtcol {
          typealias Element = Int // 使用 typealias 指定为 Int
          var list = [Element]()
          func push(_ element: Element) {
              self.list.append(element)
          }
          func pop(_ element: Element) -> Element? {
              return self.list.popLast()
          }
      }
      class DoubleList: ListProtcol {
          var list = [Double]()
          func push(_ element: Double) {// 自动推断
              self.list.append(element)
          }
          func pop(_ element: Double) -> Double? {
              return self.list.popLast()
          }
      }
  22. 什么时候使用 final
    1. final 用于限制继承和重写. 如果只是需要在某一个属性前加一个 final。 如果需要限制整个类无法被继承, 那么可以在类名之前加一个final​​​​​​​
  23. 定义静态方法时关键字 static 和 class 有什么区别
    1. ​​​​​​​​​​​​​​​​​​​​​static 定义的方法不可以被子类继承, class 则可以
    2. class AnotherClass {
          static func staticMethod(){}
          class func classMethod(){}
      }
      class ChildOfAnotherClass: AnotherClass {
          override class func classMethod(){}
          //override static func staticMethod(){}// error
      }
  24. Self 的使用场景
    1. Self 通常在协议中使用, 用来表示实现者或者实现者的子类类型. 例如, 定义一个复制的协议
    2. protocol CopyProtocol {
          func copy() -> Self
      }
    3. 如果是结构体去实现, 要将Self 换为具体的类型
    4. struct SomeStruct: CopyProtocol {
          let value: Int
          func copySelf() -> SomeStruct {
              return SomeStruct(value: self.value)
          }
      }
    5. 如果是类去实现, 则有点复杂, 需要有一个 required 初始化方法
    6. class SomeCopyableClass: CopyProtocol {
          func copySelf() -> Self {
              return type(of: self).init()
          }
          required init(){}
      }
  25. 一个类型表示选项,可以同时表示有几个选项选中(类似 UIViewAnimationOptions ),用什么类型表示
    1. OptionSet, 一般使用 struct 实现. 由于 OptionSet 要求有一个不可失败的init(rawValue:) 构造器, 而 枚举无法做到这一点(枚举的原始值构造器是可失败的, 而且有些组合值, 是没办法用一个枚举值表示的)
    2. 选项
      struct SomeOption: OptionSet {
          let rawValue: Int
          static let option1 = SomeOption(rawValue: 1 << 0)
          static let option2 =  SomeOption(rawValue:1 << 1)
          static let option3 =  SomeOption(rawValue:1 << 2)
      }
      let options: SomeOption = [.option1, .option2]
  26. inout 的作用
    1. 输入输出参数, 如:
    2.  
      func swap( a: inout Int, b: inout Int) {
          let temp = a
          a = b
          b = temp
      }
      var a = 1
      var b = 2
      print(a, b)// 1 2
      swap(a: &a, b: &b)
      print(a, b)// 2 1
  27. Error 如果要兼容 NSError 需要做什么操作
    1. 其实直接转换就可以, 例如 SomeError.someError as NSError 但是这样没有错误码, 描述等等, 如果想和 NSError 一样有这些东西, 只需要实现 LocalizedErrorCustomNSError 协议, 有些方法有默认实现, 可以略过, 如:
    2.   
      enum SomeError: Error, LocalizedError, CustomNSError {
          case error1, error2
          public var errorDescription: String? {
              switch self {
              case .error1:
                  return "error description error1"
              case .error2:
                  return "error description error2"
              }
          }
          var errorCode: Int {
              switch self {
              case .error1:
                  return 1
              case .error2:
                  return 2
              }
          }
          public static var errorDomain: String {
              return "error domain SomeError"
          }
          public var errorUserInfo: [String : Any] {
              switch self {
              case .error1:
                  return ["info": "error1"]
              case .error2:
                  return ["info": "error2"]
              }
          }
      }
      print(SomeError.error1 as NSError)
      // Error Domain=error domain SomeError Code=1 "error description error1" UserInfo={info=error1}
  28. 什么是高阶函数
    1. 一个函数如果可以以某一个函数作为参数, 或者是返回值, 那么这个函数就称之为高阶函数, 如 map, reduce, filter
  29. 如何解决引用循环
    1. 转换为值类型, 只有类会存在引用循环, 所以如果能不用类, 是可以解引用循环的
    2. delegate 使用 weak 属性
    3. 闭包中, 对有可能发生循环引用的对象, 使用 weak 或者 unowned, 修饰
  30. 下面的代码会不会崩溃,说出原因
    1. var mutableArray = [1,2,3]
      for _ in mutableArray {
          mutableArray.removeLast()
      }
    2. 不会,removeLast如果是空数组会崩溃,在for等同于一个空判断的迭代器,只要有值才执行
  31. 给集合中元素是字符串的类型增加一个扩展方法,应该怎么声明
    1.  
      extension Array where Element == String {
          var isStringElement:Bool {
              return true
          }
      }
      ["1", "2"].isStringElement
      //[1, 2].isStringElement// error
  32.  一个 Sequence 的索引是不是一定从 0 开始?
    1. sequence是相同类型集合的迭代器,迭代器不是数组,索引是可以继续迭代还是重新开始,所以它不一定是从0开始,跟序号索引不强绑定,它是next,不是从0开始
  33. 数组都实现了哪些协议
    1. MutableCollection, 实现了可修改的数组
    2. ExpressibleByArrayLiteral, 实现了数组可以从[1, 2, 3] 这种字面值初始化的能力
  34. 如何让自定义对象支持字面量初始化
    1. ExpressibleBy____Literal
    2. ExpressibleByArrayLiteral 可以由数组形式初始化
    3. ExpressibleByDictionaryLiteral 可以由字典形式初始化
    4. ExpressibleByNilLiteral 可以由nil 值初始化
    5. ExpressibleByIntegerLiteral 可以由整数值初始化
    6. ExpressibleByFloatLiteral 可以由浮点数初始化
    7. ExpressibleByBooleanLiteral 可以由布尔值初始化
    8. ExpressibleByUnicodeScalarLiteral
    9. ExpressibleByExtendedGraphemeClusterLiteral
    10. ExpressibleByStringLiteral
    11. Bool : ExpressibleByBooleanLiteral
      Int : ExpressibleByIntegerLiteral
      Float、Double : ExpressibleByIntegerLiteral、ExpressibleByFloatLiteral
      Dictionary : ExpressibleByDictionaryLiteral
      String : ExpressibleByStringLiteral
      Array、Set : ExpressibleByArrayLiteral
      Optinal : ExpressibleByNilLiteral
      class MyUrl{
         var url:URL
         init(string: String){
            self.url = URL(string: string)
         }
      }
      
      extension myUrl:ExpressibleByStringLiteral {
          init(stringLiteral value: String) {
              self.url = URL(string: value)
          }
      }
      
      let url:myUrl = "https://www.baidu.com"
      print(url.url) // "https://www.baidu.com"
      
      var num: Int = true //错误
      
      extension Int : ExpressibleByBooleanLiteral {
          public init(booleanLiteral value: Bool) {
              self = value ? 1 : 0
          }
      }
      var num: Int = true //正确
      print(num) // 输出:1

       
  35. 为什么数组索引越界会崩溃,而字典用下标取值时 key 没有对应值的话返回的是 nil 不会崩溃
    1. 数组是一段连续的地址,越界也是可以访问到那一片内存的,但是不合法的访问就是野指针
    2. 字典不一样,它存储的是指针,不是真真正的,找不到就返回nil
  36. 一个函数的参数类型只要是数字(Int、Float)都可以,要怎么表示
    1.  
      Int、Float 都有一个协议 
      func myMethod(_ value: T) where T: Numeric { 
          print(value + 1) 
      } 
      或者 ExpressibleByIntegerLiteral 协议也行
      
  37. 不通过继承,代码复用(共享)的方式有哪些
    1. Extensions
    2. ​​​​​​​Protocols
  38. 如何自定义模式匹配
    1. infix operator =~ 
      func =~ (str: String, pattern: String) -> Bool {
      } 
      infix、 prefix、 postfix 用于自定义表达式的声明, 分别表示 中缀、前缀、后缀
      

      Swift 中没有内置的正则表达式,有一个相似的功能,就是匹配模式

  39. swift语法糖?!的本质
    1. ? 和 ! 其实分别是Swift语言中对一种可选类型( Optional) 操作的语法糖,​​​​​​​Optional其实是个enum,里面有NoneSome两种类型。其实所谓的nil就是Optional.None , 非nil就是Optional.Some, 然后会通过Some(T)包装(wrap)原始值,这也是为什么在使用Optional的时候要拆包(从enum里取出来原始值)的原因
    2. var name: String?
      // 上面这个Optional的声明,是”我声明了一个Optional类型值,
       它可能包含一个String值,也可能什么都不包含”,
      也就是说实际上我们声明的是Optional类型,而不是声明了一个String类型 
      (这其实理解起来挺蛋疼的...)
  40. 什么是函数式编程
    1. 编程程序的一种代码规范,主要思想是把运算过程尽量写成一系列嵌套的函数调用
    2. 它使代码更像自然语言,告诉程序员要干什么,而不是怎么干,把怎么干的细节拆分到各个函数中。例如1+1=,那么就变成一加一
    3. 特点:
      1. 代码简洁,开发快速
      2. 接近自然语言,易于理解
      3. 更方便的代码管理。函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同
      4. 易于"并发编程"。函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题
  41. ​​​​​​​​​​​​​​

相关文章:

  • 天猫网站平面广告/常德seo公司
  • 公司logo生成器免费/百度网站排名优化软件
  • 电商wordpress和thinkphp/seo关键词优化推广报价表
  • 杭州建德网站建设/seo是做什么工作内容
  • 吴中seo网站优化软件/seo是免费的吗
  • 空气净化器用什么网站做外贸/以品牌推广为目的的广告网络平台
  • 百家CMS代码审计
  • SpringSecurity (二) --------- 认证
  • Java设计模式实战 - 02 工厂类获取设备连接器 DeviceConnectorFactory
  • 分享30个有趣的 Python小游戏,我能玩一天
  • Sqlilabs靶场1-10关详解(Get请求式)
  • Redis集群(五)
  • 深入理解Linux内核-进程
  • 【RocketMQ】第二篇-RocketMQ解决分布式事务
  • 卷积神经网络 语义分割,卷积神经网络 语义分析
  • 【vue】部署
  • 国产数据库备份恢复(TiDB\达梦\OceanBase\openGauss\GaussDB\GBASE)——筑梦之路
  • 2.1.教你如何在VMware上创建虚拟机以及安装Linux操作系统