swift学习资料2022
目录
String 与 NSString 的关系与区别
Swift字符串的Range截取
throws 和 rethrows 的用法与作用
fileprivate和internal修饰符
open与public的区别?
swift中 closure 与OC中block的区别
swift中,如何阻止方法,属性,下标被子类改写?
associatedtype 的作用
try? 和 try!是什么意思
map、filter、reduce 的作用?
defer、guard的作用?
如何自定义下标获取
这段复杂的代码按字母顺序对名称数组进行排序。尽可能简化闭包。
什么是可选的,可选可以解决哪些问题?
构体和类之间的主要区别。
什么是泛型(通用类型)?它们解决了什么问题?
nil 和 .none有什么区别?
Swift和OC的区别?
swift的派发机制
Struct和Class区别
swift中mutating的作用?
associatedtype 的作用?
什么时候使用 final
定义静态方法时关键字 static 和 class 有什么区别
Self 的使用场景
一个类型表示选项,可以同时表示有几个选项选中(类似 UIViewAnimationOptions ),用什么类型表示
inout 的作用
Error 如果要兼容 NSError 需要做什么操作
什么是高阶函数
如何解决引用循环
下面的代码会不会崩溃,说出原因
给集合中元素是字符串的类型增加一个扩展方法,应该怎么声明
一个 Sequence 的索引是不是一定从 0 开始?
数组都实现了哪些协议
如何让自定义对象支持字面量初始化
为什么数组索引越界会崩溃,而字典用下标取值时 key 没有对应值的话返回的是 nil 不会崩溃
一个函数的参数类型只要是数字(Int、Float)都可以,要怎么表示
不通过继承,代码复用(共享)的方式有哪些
如何自定义模式匹配
swift语法糖?!的本质
什么是函数式编程
String 与 NSString 的关系与区别
- Swift的String是struct,而NSString类是NSObject
- 什么时候用NSString:
- NSString特有操作和动态特性
- NSString有containsString,string只能用rangeOfString
- String与Range配合比较麻烦
- 什么情况下使用String:
- String更符合字符串“不变”特性,性能提升
- String实现了像CollectionType的接口。比如for...in的枚举遍历所有字
Swift字符串的Range截取
let str = "123456789" let start = str.startIndex//表示str的开始位置 let end = str.endIndex//表示str的结束位置 let startOffset = str.index(start, offsetBy: 2)//表示str的开始位置 + 2 let endOffset = str.index(end, offsetBy: -2)//表示str的结束位置 - 2print(str[start])//输出 1 第1个字符 print(str[startOffset])//输出 3 第3个字符 print(str[endOffset])//输出 8 第8个字符(10-2) print(str[end])//报错!因为实endIndex指向第10个字符,而第10个字符是不存在的let range1:ClosedRange = 1 ... 4 let range2:CountableClosedRange = 1 ... 4 let range3:Range = 1 ..< 4 let range4:CountableRange = 1 ..< 4let array = ["a", "b", "c", "d", "e", "f"] print(array[range1]) print(array[range2]) print(array[range3]) print(array[range4])输出: ["b", "c", "d", "e"] ["b", "c", "d", "e"] ["b", "c", "d"] ["b", "c", "d"]
throws 和 rethrows 的用法与作用
- throws:抛出异常,要do catch try
- rethrows:针对的不是函数或者方法本身,而是他携带的闭包类型的参数,当他的闭包类型的参数throws的时候,我们要使用rethrows将这个异常向上传递
fileprivate和internal修饰符
- fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。
- internal:(默认访问级别,internal修饰符可写可不写)
internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。 - open > public > internal > fileprivate > private
open与public的区别?
- public:可以别任何人访问,但是不可以被其他module复写和继承。
- open:可以被任何人访问,可以被继承和复写。
swift中 closure 与OC中block的区别
- closure是匿名函数、block是一个结构体对象
- closure则默认给外部访问的变量加上了__block修饰词的block。
- 逃逸闭包,一般用于异步,函数结束了,逃逸闭包也还没有结束,要闭包执行完才结束,所以一般逃逸闭包,要考虑循环引用的问题。
swift中,如何阻止方法,属性,下标被子类改写?
- final 关键字声明类、属性、方法和下标。
final 声明的类不能被继承,final 声明的属性、方法和下标不能被重写。
如果只是限制一个方法或属性被重写,只需要在该方法或者属性前加一个 final.
如果需要限制整个类无法被继承, 那么可以在类名之前加一个final。
- final 关键字声明类、属性、方法和下标。
associatedtype 的作用
- 关联类型: 类似于协议中的泛型,提高代码的复用性,为协议中的某个类型提供了一个别名,其代表的真实类型在具体实现中定义
- 泛型(generic)可以使我们在程序代码中定义一些可变的部分,在运行的时候指定。
使用泛型可以最大限度地重用代码、保护类型的安全以及提高性能。 //协议,使用关联类型 protocol TableViewCell {associatedtype Tfunc updateCell(_ data: T) }//遵守TableViewCell class MyTableViewCell: UITableViewCell, TableViewCell {typealias T = Modelfunc updateCell(_ data: Model) {// do something ...} }
try? 和 try!是什么意思
- try?不处理错误,抛出异常函数时, 如果函数抛出异常, 则返回 nil, 否则返回函数返回值的可选值,
- try!保证不会出现错误 强制解,抛出异常的时候崩溃, 否则则返会函数返回值
map、filter、reduce 的作用?
- [1, 2, 3].map{"\($0)"}// 一一映射成另外样子,count不变,数字数组转换为字符串数组,["1", "2", "3"]
- [1, 2, 3].filter{$0 % 2 == 0} // 筛选偶数,2
- [1, 2, 3].reduce(""){$0 + "\($1)"}//多个浓缩转换成一个, 转换为字符串并拼接,"123"
defer、guard的作用?
- defer:主要的作用是延迟执行以及在return之前执行。
如何自定义下标获取
- 实现 subscript 即可,索引除了数字之外, 其他类型也是可以的
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]} }
这段复杂的代码按字母顺序对名称数组进行排序。尽可能简化闭包。
类型推断系统会自动判断闭包中参数的类型和返回类型,就可以去掉类型:animals.sort { (one, two) -> Bool inreturn one < two } 可以用$I符号替换参数名:animals.sort { return $0 < $1 } 在单语句闭包中,可以省略返回关键字。最后一条语句的值将成为闭包的返回值:animals.sort { $0 < $1 } 后,由于Swift知道数组的元素符合equatable,因此可以简单地编写:animals.sort(by: <)
什么是可选的,可选可以解决哪些问题?
- 使用可选类型(optionals)来处理值可能缺失的情况。在objective-c中,只有在使用nil特殊值的引用类型中才可以表示值缺失。值类型(如int或float)不具有此功能。
Swift将缺乏值概念扩展到引用类型和值类型。可选变量可以包含值或零,表示是否缺少值。
- 使用可选类型(optionals)来处理值可能缺失的情况。在objective-c中,只有在使用nil特殊值的引用类型中才可以表示值缺失。值类型(如int或float)不具有此功能。
构体和类之间的主要区别。
- 类支持继承;结构不支持。
类是引用类型;结构体是值类型。
- 类支持继承;结构不支持。
什么是泛型(通用类型)?它们解决了什么问题?
- 提高代码的复用性。
- 在swift中,可以在函数和数据类型中使用泛型,例如在类、结构体或枚举中。
泛型解决了代码重复的问题。当有一个方法接受一种类型的参数时,通常会复制它以适应不同类型的参数。
例如,在下面的代码中,第二个函数是第一个函数的“克隆”,但它接受字符串而不是整数。 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 协议的任何类型。此代码实现了预期的结果,并防止传递不同类型的参数。
nil 和 .none有什么区别?
- 没有区别,none == nil
Swift和OC的区别?
- swift是静态语言,有类型推断,OC是动态语言。
- swift面向协议编程,OC面向对象编程
- swift注重值类型,OC注重引用类型。
- swift支持泛型,OC只支持轻量泛型
- swift支持静态派发(效率高)、动态派发(函数表派发、消息派发)方式,OC支持动态派发(消息派发)方式。
- swift支持函数式编程,swift的协议不仅可以被类实现,也可以被struct和enum实现
- swift有元组类型、支持运算符重载,swift支持命名空间,swift支持默认参数
- swift比oc代码更加简洁
- swift语法简单易读、代码更少,更加清晰、易于维护
- 更加安全,optional的使用更加考验 程序员 对代码安全的掌控
- 泛型、结构体、枚举都很强大
- 函数为一等公民,便捷的函数式编程
- 有命名空间 基于module
- 类型判断
swift的派发机制
- 三种派发机制:直接派发, 函数表派发 和 消息机制派发
- 直接派发 :最快指令集更少, 编译器有很大的优化空间, 例如函数内联等,但缺乏动态性,没继承,静态调用。
- 函数表派发:使用了一个数组存储类声明和函数指针. 称为虚函数表。查表比直接派发慢. 从字节码角度看, 多两次读和一次跳转的损耗. 另一个慢在于编译器无法优化.这种基于数组, 缺陷在于无法拓展. 子类会在最后插入新的函数, 没有位置可以让 extension 安全地插入函数.
- 消息机制派发:是oc的消息转发机制,是最动态的方式. 效率最低,但是缓存后跟函数表派发一样快
- Swift 的派发机制:使用 dynamic 修饰的时候会通过 Objective-C 的运行时进行消息机制派发.总结起来有这么几点:
- 值类型、协议和类的extension总是会使用直接派发
- NSObject 声明作用域里的函数都会使用函数表进行派发.
- 协议里声明的, 并且带有默认实现的函数会使用函数表进行派发.
- NSObject 的 extension 会使用消息机制进行派发
- 指定派发方式
- 直接派发:final、static、@inline
- 消息派发:dynamic、@objc
- 三种派发机制:直接派发, 函数表派发 和 消息机制派发
Struct和Class区别
- Struct不支持继承、Class支持继承
- Struct是值类型,Class是引用类型
- Struct无法修改自身属性值,函数需要添加mutating关键字
- Struct初始化方法是基于属性的
- Struct不需要deinit方法,因为值类型不关心引用计数,Class需要deinit方法。
swift中mutating的作用?
- swift中协议是可以被Struct和enum实现的,mutating关键字是为了能在被修饰的函数中修改struct或enum的变量值。对Class完全透明。
associatedtype 的作用?
- 简单来说就是 protocol 使用的泛型
protocol ListProtcol {associatedtype Elementfunc push(_ element:Element)func pop(_ element:Element) -> Element? }
- 实现协议的时候, 可以使用 typealias 指定为特定的类型, 也可以自动推断, 如
class IntList: ListProtcol {typealias Element = Int // 使用 typealias 指定为 Intvar 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()} }
什么时候使用 final
- final 用于限制继承和重写. 如果只是需要在某一个属性前加一个 final。 如果需要限制整个类无法被继承, 那么可以在类名之前加一个final
定义静态方法时关键字 static 和 class 有什么区别
- static 定义的方法不可以被子类继承, class 则可以
class AnotherClass {static func staticMethod(){}class func classMethod(){} } class ChildOfAnotherClass: AnotherClass {override class func classMethod(){}//override static func staticMethod(){}// error }
Self 的使用场景
- Self 通常在协议中使用, 用来表示实现者或者实现者的子类类型. 例如, 定义一个复制的协议
protocol CopyProtocol {func copy() -> Self }
- 如果是结构体去实现, 要将Self 换为具体的类型
struct SomeStruct: CopyProtocol {let value: Intfunc copySelf() -> SomeStruct {return SomeStruct(value: self.value)} }
- 如果是类去实现, 则有点复杂, 需要有一个 required 初始化方法
class SomeCopyableClass: CopyProtocol {func copySelf() -> Self {return type(of: self).init()}required init(){} }
一个类型表示选项,可以同时表示有几个选项选中(类似 UIViewAnimationOptions ),用什么类型表示
- OptionSet, 一般使用 struct 实现. 由于 OptionSet 要求有一个不可失败的init(rawValue:) 构造器, 而 枚举无法做到这一点(枚举的原始值构造器是可失败的, 而且有些组合值, 是没办法用一个枚举值表示的)
- 选项
struct SomeOption: OptionSet {let rawValue: Intstatic 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]
inout 的作用
- 输入输出参数, 如:
func swap( a: inout Int, b: inout Int) {let temp = aa = bb = temp } var a = 1 var b = 2 print(a, b)// 1 2 swap(a: &a, b: &b) print(a, b)// 2 1
Error 如果要兼容 NSError 需要做什么操作
- 其实直接转换就可以, 例如
SomeError.someError as NSError
但是这样没有错误码, 描述等等, 如果想和 NSError 一样有这些东西, 只需要实现LocalizedError
和CustomNSError
协议, 有些方法有默认实现, 可以略过, 如: enum SomeError: Error, LocalizedError, CustomNSError {case error1, error2public 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 1case .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}
- 其实直接转换就可以, 例如
什么是高阶函数
- 一个函数如果可以以某一个函数作为参数, 或者是返回值, 那么这个函数就称之为高阶函数, 如 map, reduce, filter
如何解决引用循环
- 转换为值类型, 只有类会存在引用循环, 所以如果能不用类, 是可以解引用循环的
- delegate 使用 weak 属性
- 闭包中, 对有可能发生循环引用的对象, 使用 weak 或者 unowned, 修饰
下面的代码会不会崩溃,说出原因
var mutableArray = [1,2,3] for _ in mutableArray {mutableArray.removeLast() }
- 不会,removeLast如果是空数组会崩溃,在for等同于一个空判断的迭代器,只要有值才执行
给集合中元素是字符串的类型增加一个扩展方法,应该怎么声明
extension Array where Element == String {var isStringElement:Bool {return true} } ["1", "2"].isStringElement //[1, 2].isStringElement// error
一个 Sequence 的索引是不是一定从 0 开始?
- sequence是相同类型集合的迭代器,迭代器不是数组,索引是可以继续迭代还是重新开始,所以它不一定是从0开始,跟序号索引不强绑定,它是next,不是从0开始
数组都实现了哪些协议
- MutableCollection, 实现了可修改的数组
- ExpressibleByArrayLiteral, 实现了数组可以从[1, 2, 3] 这种字面值初始化的能力
如何让自定义对象支持字面量初始化
ExpressibleBy____Literal
ExpressibleByArrayLiteral
可以由数组形式初始化ExpressibleByDictionaryLiteral
可以由字典形式初始化ExpressibleByNilLiteral
可以由nil 值初始化ExpressibleByIntegerLiteral
可以由整数值初始化ExpressibleByFloatLiteral
可以由浮点数初始化ExpressibleByBooleanLiteral
可以由布尔值初始化- ExpressibleByUnicodeScalarLiteral
- ExpressibleByExtendedGraphemeClusterLiteral
- ExpressibleByStringLiteral
Bool : ExpressibleByBooleanLiteral Int : ExpressibleByIntegerLiteral Float、Double : ExpressibleByIntegerLiteral、ExpressibleByFloatLiteral Dictionary : ExpressibleByDictionaryLiteral String : ExpressibleByStringLiteral Array、Set : ExpressibleByArrayLiteral Optinal : ExpressibleByNilLiteral
class MyUrl{var url:URLinit(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
为什么数组索引越界会崩溃,而字典用下标取值时 key 没有对应值的话返回的是 nil 不会崩溃
- 数组是一段连续的地址,越界也是可以访问到那一片内存的,但是不合法的访问就是野指针
- 字典不一样,它存储的是指针,不是真真正的,找不到就返回nil
一个函数的参数类型只要是数字(Int、Float)都可以,要怎么表示
Int、Float 都有一个协议 func myMethod(_ value: T) where T: Numeric { print(value + 1) } 或者 ExpressibleByIntegerLiteral 协议也行
不通过继承,代码复用(共享)的方式有哪些
- Extensions
- Protocols
如何自定义模式匹配
infix operator =~ func =~ (str: String, pattern: String) -> Bool { } infix、 prefix、 postfix 用于自定义表达式的声明, 分别表示 中缀、前缀、后缀
Swift 中没有内置的正则表达式,有一个相似的功能,就是匹配模式
swift语法糖?!的本质
?
和!
其实分别是Swift语言中对一种可选类型( Optional) 操作的语法糖,Optional
其实是个enum
,里面有None
和Some
两种类型。其实所谓的nil就是Optional.None
, 非nil就是Optional.Some
, 然后会通过Some(T)
包装(wrap)原始值,这也是为什么在使用Optional
的时候要拆包(从enum
里取出来原始值)的原因var name: String? // 上面这个Optional的声明,是”我声明了一个Optional类型值,它可能包含一个String值,也可能什么都不包含”, 也就是说实际上我们声明的是Optional类型,而不是声明了一个String类型 (这其实理解起来挺蛋疼的...)
什么是函数式编程
- 编程程序的一种代码规范,主要思想是把运算过程尽量写成一系列嵌套的函数调用
- 它使代码更像自然语言,告诉程序员要干什么,而不是怎么干,把怎么干的细节拆分到各个函数中。例如1+1=,那么就变成一加一
- 特点:
- 代码简洁,开发快速
- 接近自然语言,易于理解
- 更方便的代码管理。函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同
- 易于"并发编程"。函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题
-
swift学习资料2022相关推荐
- Apple Swift学习资料汇总
[更新]Apple Swift学习资料汇总 1月16日厦门 OSC 源创会火热报名中,奖品多多哦 » 今年的苹果开发者大会(WWDC)上,公布了ios8的几个新特性,其中包括引入了群聊功能,支持第 ...
- swift 学习资料大全
版本:Swift github排名 https://github.com/trending,github搜索:https://github.com/search 主要工作说明: 1. 将Swift从 ...
- 全面的Swift学习资料整理
资料1 ---教程类 官方文档中文翻译http://wiki.jikexueyuan.com/project/swift/Github上的地址点我 Using Swift with Cocoa and ...
- 汇集了很多swift 学习指南
https://github.com/ipader/SwiftGuide 1,059 Unstar 7,294 Fork1,966 ipader/SwiftGuide Code Issues 0 ...
- iOS 学习资料整理
这份学习资料是为 iOS 初学者所准备的, 旨在帮助 iOS 初学者们快速找到适合自己的学习资料, 节省他们搜索资料的时间, 使他们更好的规划好自己的 iOS 学习路线, 更快的入门, 更准确的定位的 ...
- iOS 学习资料整理(中文版)
这份学习资料是为 iOS 初学者所准备的, 旨在帮助 iOS 初学者们快速找到适合自己的学习资料, 节省他们搜索资料的时间, 使他们更好的规划好自己的 iOS 学习路线, 更快的入门, 更准确的定位的 ...
- iOS 学习资料大全
转: http://segmentfault.com/a/1190000002473595 这份学习资料是为 iOS 初学者所准备的, 旨在帮助 iOS 初学者们快速找到适合自己的学习资料, 节省他 ...
- 信奥中的数学学习资料汇总(2022.10.31)
信奥中的数学之入门组(面向小学四年级至六年级以及初一学生) 信奥中的数学之入门组(面向小学四年级至六年级以及初一学生)_dllglvzhenfeng的博客-CSDN博客 信奥中的数学学习:小学.初高中 ...
- 2022最新Android开发全套学习资料(知识笔记+技能图谱)3-5年开发者进阶提升
前言 本人2013年由 java 转到 Android 开发,十年间,我从小厂打杂到进入到核心团队,再跳槽到大厂,在华为呆过一段时间,18年四月份进了阿里一直到现在.这期间,我见证过很多人的成败起落, ...
最新文章
- 发布了!2020年AI人才发展报告,最高补助1000万!
- jupyter代码字体大小_你可能并不知道这样定制炫酷的jupyter主题
- [APP] Android 开发笔记 001-环境搭建与命令行创建项目
- python子类继承父类属性实例_python – 从子类内的父类访问属性
- linux命令行大全 笔记,《Linux命令行大全》读书笔记
- mysql5.7.17免安装版_MySql 5.7.17免安装配置
- emq数据储存到mysql,规则引擎示例 - 保存数据到 MySQL - 《EMQ X Enterprise v4.0 中文文档》 - 书栈网 · BookStack...
- Okio 1.9简单入门
- android stl,Android NDK中的c++ STL
- 第4章 基本TCP套接口编程
- PyTorch 算法加速指南
- java计算机毕业设计O2O生鲜果蔬电商设计与实现(附源码、数据库)
- mac怎么验机,都应该查什么
- cgcs2000大地坐标系地图_我国大地坐标系_地图与地图制图
- DDD中的值对象和实体
- Microsoft Word 设置底纹
- Spark Core项目实战(3) | 页面单跳转化率统计
- torch.roll() 函数用法
- ps去掉多余的人物#ps抠图#ps去除抠图教程学习入门基础学习
- DC/DC电源模块直流升压线性可调正负输出5v12v24v转0-±50v/±110v/±200v/±250v/±360v/±500v
热门文章
- php 如何让两张图片重叠,php多张图片合并方法分享
- 那些可以加速国内外开源库的免费CDN
- 【深度学习实战03】——YOLO tensorflow运行及源码解析
- 【Oracle】SCOTT用户和HR用户
- Future.get()抛出ExecutionException或InterruptedException?
- Apache Calcite教程-SQL解析-Calcite SQL解析
- C语言牛客网(NowCoder)刷题篇
- 最全MySQL8.0实战教程 14 MySQL的存储过程 14.1 概述
- Arduino压电震动传感器
- Redis之Redis基础、环境搭建、主从切换