美文网首页Swift学习
Swift 面试总结 (上)

Swift 面试总结 (上)

作者: Michael1 | 来源:发表于2017-05-08 17:26 被阅读51次

    1.Swift 到底是面向对象还是函数式的编程语言?

    Swift 既是面向对象的,又是函数式的编程语言。
    说 Swift 是 Object-oriented,是因为 Swift 支持类的封装、继承、和多态,从这点上来看与 Java 这类纯面向对象的语言几乎毫无差别。
    说 Swift 是函数式编程语言,是因为 Swift 支持 map, reduce, filter, flatmap 这类去除中间状态、数学函数式的方法,更加强调运算结果而不是中间过程。
    1.map、filter、reduce 的作用

    • map 是Array类的一个方法,我们可以使用它来对数组的每个元素进行转换
    let intArray = [1, 3, 5]
    let stringArr = intArray.map {
              return "\($0)"
          }
    // ["1", "3", "5"]
    
    • filter 用于选择数组元素中满足某种条件的元素
    let filterArr = intArray.filter {
      return $0 > 1
    }
    //[3, 5]
    
    • reduce 把数组元素组合计算为一个值
    let result = intArray.reduce(0) {
      return $0 + $1
    }
    //9
    

    1.map 与 flatmap 的区别

    • map 可以对一个集合类型的所有元素做一个映射操作
    • 对数组进行flatmap操作,和map是没有区别的
    • 和map 不同,flatmap 有两个定义,分别是:
    func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
    func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
    

    1)第一种情况返回值类型是 T?, 实际应用中,可以用来过滤元素为nil的情况,(内部使用了 if-let 来对nil值进行了过滤) 例如:

    let optionalArray: [String?] = ["AA", nil, "BB", "CC"];
    var optionalResult = optionalArray.flatMap{ $0 }
    // ["AA", "BB", "CC"]
    操作前是[String?], 操作后会变成[String]
    

    2)第二种情况会自动去重处理

    let numbersCompound = [[1,2,3],[4,5,6]];
    var res = numbersCompound.map { $0.map{ $0 + 2 } }
    // [[3, 4, 5], [6, 7, 8]]
    var flatRes = numbersCompound.flatMap { $0.map{ $0 + 2 } }
    // [3, 4, 5, 6, 7, 8]
    

    $0.map{ $0 + 2 } 会得到[3, 4, 5], [6, 7, 8], 然后遍历这两个数组,将遍历的元素拼接到一个新的数组内,最终并返回就得到了[3, 4, 5, 6, 7, 8]

    2.Swift 中 struct 和 class 什么区别?举个应用中的实例

    • struct没有继承的功能,而class是可以继承的,这是面向对象语言的核心能力,class当然会有这个能力。
    • struct 是值类型,class 是引用类型。体现在内存使用上,struct是通过值传递,而class是通过引用传递的。
      看过WWDC的人都知道,struct 是苹果推荐的,原因在于它在小数据模型传递和拷贝时比 class 要更安全,在多线程和网络请求时尤其好用。我们来看一个简单的例子:
    class A {
       var val = 1
    }
    var a = A()
    var b = a
    b.val = 2
    

    此时 a 的 val 也被改成了 2,因为 a 和 b 都是引用类型,本质上它们指向同一内存。解决这个问题的方法就是使用 struct:

    struct A {
      var val = 1
    }
    var a = A()
    var b = a
    b.val = 2
    

    此时 A 是struct,值类型,b 和 a 是不同的东西,改变 b 对于 a 没有影响。

    3. Swift 中定义常量和 Objective-C 中定义常量有什么区别?

    OC是这样定义常量的:
    const int number = 0;
    Swift 是这样定义常量的:
    let number = 0

    • OC中用 const 来表示常量,而 Swift 中用 let 来判断是不是常量。
    • OC中 const 表明的常量类型和数值是在 compilation time (编译阶段)时确定的;而 Swift 中 let 只是表明常量(只能赋值一次),其类型和值既可以是静态的,也可以是一个动态的计算方法,它们在 runtime 时确定的。

    4.Swift 中的泛型

    泛型是为Swift编程灵活性的一种语法,在函数、枚举、结构体、类中都得到充分的应用,它的引入可以起到占位符的作用,当类型暂时不确定的,只有等到调用函数时才能确定具体类型的时候可以引入泛型。
    我们之前实际上已经使用过泛型,例如:Swift的Array和Dictionary类型都是泛型集。
    详细介绍点我

    5.给一个数组,要求写一个函数,交换数组中的两个元素

    func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
        (nums[p], nums[q]) = (nums[q], nums[p])
    }
    

    6.实现一个 min 函数,返回两个元素较小的元素

    func min<T: Comparable>(_ a: T, _ b: T) -> T {
        return a < b ? a: b
    }
    //这里一定要遵守 Comparable 协议,因为并不是所有的类型都具有“可比性”
    

    7.guard 使用场景

    • 使用 guard 来表达 “提前退出”的意图,有以下 使用场景 :
    • 在验证入口条件时
    • 在成功路径上提前退出
    • 在可选值解包时(拍扁 if let..else 金字塔)
    • return 和 throw 中
    • 日志、崩溃和断言中

    而下面则是尽量 避免使用 的场景:

    • 不要用 guard :替代琐碎的 if..else 语句
    • 不要用 guard :作为 if 的相反情况
    • 不要:在 guard 的 else 语句中放入复杂代码
      具体介绍点这里

    8.defer 使用场景

    defer 语句用于在退出当前作用域之前执行代码.例如:
    手动管理资源时,比如 关闭文件描述符,或者即使抛出了错误也需要执行一些操作时,就可以使用 defer 语句。
    如果多个 defer 语句出现在同一作用域内,那么它们执行的顺序与出现的顺序相反

    func f() {
        defer { print("First") }
        defer { print("Second") }
        defer { print("Third") }
    }
    f()
    // 打印 “Third”
    // 打印 “Second”
    // 打印 “First”
    

    9.String 与 NSString 的关系与区别

    • String 是 struct,值类型。NSString 是类,引用类型。

    10.Swift 访问关键字

    从高到低得权限控制顺序如下

    open > public > interal > fileprivate > private
    

    private
    swift3.0 private访问级别所修饰的属性或者方法只能在当前类里访问。

    class A {
        private func test() {
            print("this is private function!")
        }
    }
    
    class B: A {
        func show() {
            test()
        }
    }
    

    上面代码在swift3.0以前,可以顺利编译成功,但是在swift3.0中会编译失败,提示class B中test()方法不可用。
    fileprivate
    fileprivate是Swift3.0后新加的权限修饰符,fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。(比如上面例子中把private改成fileprivate就不会报错了)。
    internal
    internal为默认访问级别,可默认不写。internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。如果是App代码,也是在整个App代码,也是在整个App内部可以访问。
    public
    可以被任何人访问。但其他module中不可以被override和继承,而在module内可以被override和继承。
    open
    open为swift3.0后新加权限关键字,可以被任何人使用,包括override和继承。
    详细的点这里

    11.柯里化函数

    详细介绍

    相关文章

      网友评论

        本文标题:Swift 面试总结 (上)

        本文链接:https://www.haomeiwen.com/subject/wwnmtxtx.html