美文网首页iOS技术点
Swift 基本技术点(面试)

Swift 基本技术点(面试)

作者: zhang_jk | 来源:发表于2019-08-06 18:12 被阅读0次

    1.什么是函数式编程

    函数式编程其实是一种编程思想, 代码写出来只是它的表现形式

    在面向对象的编程思想中, 我们将要解决的一个个问题, 抽象成一个个类, 通过给类定义属性和方法, 让类帮助我们解决需要处理的问题.(其实面向对象也叫命令式编程, 就像给对象下一个个命令)

    而在函数式编程中, 我们则通过函数描述我们要解决的问题, 以及解决问题需要怎样的方案.

    RxSwift

    2.swif相对于OC有哪些优点

    1、swift语法简单易读、代码更少,更加清晰、易于维护

    2、更加安全,optional的使用更加考验程序员对代码安全的掌控

    3、泛型、结构体、枚举都很强大

    4、函数为一等公民,便捷的函数式编程

    5、有命名空间 基于module

    6、类型判断

    oc的优点、运行时

    什么是泛型,swift哪些地方使用了泛型?

    泛型(generic)可以使我们在程序代码中定义一些可变的部分,在运行的时候指定。使用泛型可以最大限度地重用代码、保护类型的安全以及提高性能。

    例如 optional 中的 map、flatMap 、?? (泛型加逃逸闭包的方式,做三目运算)

    defer 、guard的作用?

    defer 包含中的内容一定会在离开作用域的地方执行
    guard 过滤器,拦截器

    swift 语法糖 ? !的本质(实现原理)

    ?为optional的语法糖
    optional<T> 是一个包含了nil 和普通类型的枚举,确保使用者在变量为nil的情况下处理

    !为optional 强制解包的语法糖

    swift中模式匹配的作用?

    • 模式匹配:在switch中体现最明显
    • 通配符模式: _
    • 标识符模式: let i= 1
    • 绑定值模式: case .Student(let name) 或者 case let .Student(name)
    • 元组模式: case(let code,_)
    • 可选模式:if case let x? = someOptional{}
    • 类型转换模式: case is Int:或者 case let n as String:
    • 表达式模式:范围匹配case(0.. 30)
      if case let:if case let .Student(name) = xiaoming { }

    for case let: for case let x in array where x > 10 {} 或者 for x in array where x > 10

    swift中的closure于OC中block的区别?

    • closure是匿名函数 、block是一个结构体对象
    • 都能捕获变量
    • closure通过逃逸闭包来在block内部修改变量,block通过__block修饰符

    什么是capture list,举例说明用处?

    • 捕获列表 weak unowned

    swift中private与fileprivate的区别?

    • private的作用域被约束与被定义的当前类作用域,fileprivate作用域是整个文件

    Set 独有的方法有哪些?

    • intersect(_:)// 根据两个集合中都包含的值创建的一个新的集合

    • exclusiveOr(_:) // 根据只在一个集合中但不在两个集合中的值创建一个新的集合

    • union(_:) // 根据两个集合的值创建一个新的集合

    • subtract(_:) //根据不在该集合中的值创建一个新的集合

    • isSubsetOf(_:) //判断一个集合中的值是否也被包含在另外一个集合中

    • isSupersetOf(_:) //判断一个集合中包含的值是否含有另一个集合中所有的值

    • isStrictSubsetOf(:) isStrictSupersetOf(:) //判断一个集合是否是另外一个集合的子集合或者父集合并且和特定集合不相等

    • isDisjointWith(_:) //判断两个集合是否不含有相同的值

    实现一个min 函数

    func minNum(a: T, b: T) -> T { return a > b ? a : b }

    map、filter、reduce 的作用

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

    map 和flatMap的区别

    1、map 可以对一个集合类型的所有元素做一个映射操作
     
    2、和map 不同,flatmap 在之前版本有两个定义,分别是:
    func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
    func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
     
    swift 4.1 废弃后改为
     
    func flatMap(transform: (Self.Generator.Element) throws -> Sequence) -> [Sequence.Element]
    func flatMap(_ transform: (Wrapped) throws -> U?) rethrows -> U?
     
    1) flatMap的第一个作用和map一样,对一个集合类型的所有元素做一个映射操作,但是可以过滤为nil的情况
     
    例如:
    let array = [1,2,5,6,7,nil]
    let array_map = array.map { $0 }
    //[Optional(1), Optional(2), Optional(5), Optional(6), Optional(7), nil]
    let array_flatmap = array_map.flatMap { $0 }
    //[1, 2, 5, 6, 7]
     
    2) 第二种情况可以进行“降维”操作
     
    let array = [["1", "2"],["3", "4"]]
    let array_map = array.map { $0 }
    //[["1", "2"], ["3", "4"]]
    let array_flatmap = array_map.flatMap { $0 }
    //["1", "2", "3", "4"] 
    

    什么是copy on write

    copy on write, 写时复制,简称COW,它通过浅拷贝(shallow copy)只复制引用而避免复制值;当的确需要进行写入操作时,首先进行值拷贝,在对拷贝后的值执行写入操作,这样减少了无谓的复制耗时。
    

    如何获取当前代码的函数名和行号

    #function
    #line
    #file
    #column
    

    如何声明一个只能被类conform的protocol

    protocol:class

    String 与NSString的关系与区别

    • 两者可以随意转换

    • String为值类型,拷贝赋值需要值拷贝

    • NSString 传递指针

    如何截取String的某段字符串

            let str = "how to substring js func"
            let star = str.index(str.startIndex, offsetBy: 0)
            let end = str.index(str.startIndex, offsetBy: 4)
            let substr = str[star..<end]
            print(substr)
    

    throws 和 rethrows的用法与作用

    • 当闭包参数会抛出异常时 使用throws

    • 同时外部方法体返回结果需要 rethrows 异常

    • rethrows 可以用 throws 替换, 反过来不行

    try? 和 try!是什么意思

    • 不处理错误,抛出异常函数时, 如果函数抛出异常, 则返回 nil, 否则返回函数返回值的可选值,
    • 保证不会出现错误 强制解,抛出异常的时候崩溃, 否则则返会函数返回值

    associatedtype 的作用

    • 关联类型,关联类型为协议中的某个类型提供了一个别名,其代表的真实类型在实现者中定义
    
    protocol TableViewCell {
        associatedtype T
        func updateCell(_ data: T)
    }
    
    struct Model {
        var name:String
    
    }
    class MyTableViewCell: UITableViewCell, TableViewCell {
        typealias T = Model
        func updateCell(_ data: Model) {
            // do something
        }
    }
    

    public 和 open 的区别

    • 是否可以继承

    public 修饰符

    修饰的属性或者方法可以在其他作用域被访问
    但不能在重载 override 中被访问
    也不能在继承方法中的 Extension 中被访问

    open 修饰符

    open 其实就是过去的 public,过去 public 有两个作用:

    修饰的属性或者方法可以在其他作用域被访问
    修饰的属性或者方法可以在其他作用域被继承或重载 override

    private、fileprivate、public、open修饰符的作用和区别

    1、private 修饰符

    只允许在当前类中调用,不包括 Extension
    private 现在变为了真正的私有访问控制
    用 private 修饰的方法不可以被代码域之外的地方访问

    2、fileprivate 修饰符

    fileprivate 其实就是过去的 private。
    其修饰的属性或者方法只能在当前的 Swift 源文件里可以访问。
    即在同一个文件中,所有的 fileprivate 方法属性都是可以访问到的。

    
    class TKBase: NSObject {
        func showTest()  {
            testB()
        }
    }
    
    fileprivate func testA() {
        print("test")
    }
    
    fileprivate func testB() {
        print("testB")
    }
    
    class A: NSObject {
        fileprivate func testA() {
            print("test")
        }
    
        fileprivate func testB() {
            print("testB")
        }
    }
    
    class B: NSObject {
        func show() {
            testA()
        }
    
    
    }
    
    

    5、internal修饰符

    • 顾名思义,internal是内部的意思,即有着internal访问权限的属性和方法说明在模块内部可以访问,超出模块内部就不可被访问了。在Swift中默认就是internal的访问权限。

    从高到低排序如下:
    open > public > interal > fileprivate > private

    声明一个只有一个参数没有返回值闭包的别名

    typealias MyBlock = (Int) -> (Void)
    

    Self 的使用场景

    • 例如:协议定义的时候,如果需要使用到实现者的上下文怎么办? 我们并不知道谁会实现自己,这个时候可以使用Self进行指代

    dynamic 的作用

    • swift中的函数是静态调用,静态调用的方式会更快,但是静态调用的时候没救不能从字符串查找到对于的方法地址,这样 与OC交互的时候,OC动态查找方法就会找不到,这个时候就可以通过使用 dynamic 标记来告诉编译器,这个方法要被动态调用的

    • swift中如果KVO监听属性,那么属性就需要 dynamic 来标记

    什么时候使用@objc

    与OC 的交互部分
    KOV 监听、动态方法查找等都需要
    协议可选方法等
    

    Optional (可选型)是用什么实现的

    枚举 一个为nil,一个为属性值

    如何自定义下标获取

    class Demo: NSObject {
    
    }
    
    extension Demo {
        subscript(index: Int) -> Int {
            get {
                // 返回一个适当的 Int 类型的值
                return 9
            }
            set(newValue) {
                // 执行适当的赋值操作
            }
        }
    }
    

    inout 的作用

    让输入参数可变 类似__block的作用

    Error 如果要兼容NSError需要做什么操作

    Error是一个协议, swift中的Error 都是enum, 可以转 NSError
    如果需要Error有NSError的功能,实现 LocalizedError CustomNSError 协议
    

    下面代码都用了哪些语法糖

    [1, 2, 3].map{ $0 * 2 }

    array语法糖
    尾部闭包语法糖
    $0
    

    什么是高阶函数

    map、flatMap、filter、reduce?

    下面的代码会不会崩溃,说出原因

            var mutableArray = [1,2,3]
            for _ in mutableArray {
                mutableArray.removeLast()
            }
    
    不会,因为是值类型
    

    给集合中元素是字符串的类型增加一个扩展方法,应该怎么声明

    extension Array where Element == String {}

    定义静态方法时关键字 static 和 class 有什么区别

    非class类型 一般 统一用 static  例如  枚举 结构体
    protocol中 使用 static ,实现协议的 枚举 结构体 用 static
    class 中使用  class static 都可以
    

    一个 Sequence 的索引是不是一定从 0 开始?

    <br>

    数组都实现了哪些协议

    Decodable Encodable Equatable Hashable  CustomStringConvertible, CustomDebugStringConvertible RandomAccessCollection, MutableCollection RangeReplaceableCollection CustomReflectable ExpressibleByArrayLiteral
    

    如何自定义模式匹配

    infix operator =~
     
    func =~ (str: String, pattern: String) -> Bool {
     
         
    }
    
    infix、  prefix、  postfix  用于自定义表达式的声明, 分别表示 中缀、前缀、后缀
    

    autoclosure 的作用

    自动闭包,将参数自动封装为闭包参数
    

    下面代码中 mutating 的作用是什么

    struct Person {
     
        var name: String {
            mutating get {
                return store
            }
        }
    }
    结构体中的 属性可能发生改变
    

    如何让自定义对象支持字面量初始化

    ExpressibleByArrayLiteral
    ExpressibleByStringLiteral
    

    为什么数组索引越界会崩溃,而字典用下标取值时 key 没有对应值的话返回的是 nil 不会崩溃。

    struct Array {
        subscript(index: Int) -> Element
    }
     
    struct Dictionary {
        subscript(key: Key) -> Value?
    }
    

    一个函数的参数类型只要是数字(Int、Float)都可以,要怎么表示

    Int、Float 都有一个协议
     
    func myMethod(_ value: T) where T: Numeric {
        print(value + 1)
    } 
     
    或者 ExpressibleByIntegerLiteral 协议也行
    

    Swift的静态派发

    很显然静态派发是一种更高效的方法,因为静态派发免去了查表操作。
    
    不过静态派发是有条件的,方法内部的代码必须对编译器透明,并且在运行时不能被更改,这样编译器才能帮助我们。
    
    Swift 中的值类型不能被继承,也就是说值类型的方法实现不能被修改或者被复写,因此值类型的方法满足静态派发的要求。
    
    默认静态派发,如果需要满足动态派发,需要 dymanic修饰
    

    swift 有哪些修饰符

    open、public 、internal、fileprivate、private
    

    实现一个函数,输入任意一整数,输入要返回输入的整数 + 2

    func plusTwo(one: Int) -> (Int) -> Int {
        return { (two: Int) in return two + one }
    }
    
    plusTwo(one: 4)(2)
    

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

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

    相关文章

      网友评论

        本文标题:Swift 基本技术点(面试)

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