指南
指南的撰写尽量参考IDEA的Plugin参考文档
Property Wrapper
属性包装器,如同切面一样,当你需要对数据进行校验,或者将数据存储到数据库时,一般情况下,你需要对每个属性都写一遍代码。
通过Property Wrapper,
如何定义Property Wrapper: 定义一个结构体或类,声明属性wrappedValue
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
如何使用Property Wrapper:
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
内部实现:
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
包装器可定义自身的init构造函数以及不同的重载形式
属性投影:在@propertyWrapper中可额外定义一个projectValue属性,该属性在外部通过 a.$v
访问:
@propertyWrapper
struct SmallNumber {
private var number = 0
var projectedValue = false
var wrappedValue: Int {
get { return number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
}
struct SomeStructure {
@SmallNumber var someNumber: Int
}
var someStructure = SomeStructure()
someStructure.someNumber = 4
print(someStructure.$someNumber)
// Prints "false"
someStructure.someNumber = 55
print(someStructure.$someNumber)
// Prints "true"
所谓投影,其实就出值的状态
Access Control 访问控制
https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
访问控制限制了代码可访问性
可访问级别:
- 开发和公开:public
- 内部(默认,如果没有定义):internal或者不定义
- 文件私有(仅在源文件内部可见): fileprivate
- 定义域私有(仅在声明的域内可见): private
typealias
https://docs.swift.org/swift-book/ReferenceManual/Declarations.html
类似于c语言的typedef,为复杂的类型定义一个别名
Typealias用在protocol中,还表示这个类型是该协议的实现需要提供的一个别名,在实现中必须提供typealias A = B
/// A modifier that can be applied to a view or other view modifier,
/// producing a different version of the original value.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ViewModifier {
/// The type of view representing the body of `Self`.
associatedtype Body : View
/// Returns the current body of `self`. `content` is a proxy for
/// the view that will have the modifier represented by `Self`
/// applied to it.
func body(content: Self.Content) -> Self.Body
/// The content view type passed to `body()`.
typealias Content
}
类型:Self和Type以及其他
https://docs.swift.org/swift-book/ReferenceManual/Types.html
Swift中有两种类型: 命名的类型和组合类型
命名的类型就是包括:类(class), 结构体(struct),枚举, 协议,基本类型(数字,字符,字符串)
命名的类型可以使用extension
复合类型是没有命名的类型:函数类型以及元组类型。 (Int,(Int,Int))就是元组类型,但是注意(Int)不是,通常而言,加上括号就能构成新的组合类型。
元组类型: 既有名称,也有类型
var someTuple = (top: 10, bottom: 12) // someTuple is of type (top: Int, bottom: Int)
someTuple = (top: 4, bottom: 42) // OK: names match
someTuple = (9, 99) // OK: names are inferred
someTuple = (left: 5, right: 5) // Error: names don't match
元组类型可用于函数返回多个值
Optional: 有3种声明方式 T? 或 Optional,以及 T!
其中:T!表示的隐式解值,它的含义是:这个类型总是有值(总是不为空,一旦为空,就抛出Runtime异常)
复合协议类型: typealias PQR = P & Q & R
Opaque Type:模糊类型
定义了服从多个协议的类型,但是不必指定底层类型。模糊类型出现在函数的返回值中,语法some Constraint
, Constriant可以是class,protocol,协议组合,Any。 类中只有final的method才能返回模糊类型
Meta Type,元类型:类型的类型。类似于java中的元类型是name + .class, Swift中的元类型是 name + .Type, 协议的元类型是 name + .Protocol. 元类型的实例:通过 name + .self来访问,比如String.self, 它返回的是类型(类型是元类型的一个实例),可使用type(…)来获取类型。
Self Type:避免重复键入类型的名称,对于协议而言,Self解析成最终实现类型。
Never
https://swift.gg/2018/08/30/never/
Never类似于其他语言中的,仅仅用于标注不可能的事情,因为Never没有实例话方法,所以不可能构造Never的实例,因此也就没有可能返回Never类型。
如果一个别名定义为Never, typealias Body = Never
,则表明这个类型没有值,也就是说协议里面没有实现这个类型。
注意,语言是静态的,只有写代码的人知道代码将会发生什么。就像函数都有返回值,这是语言的假定,但是某些场景中,这个函数就一定不会返回,这就是Never的作用:进一步提示。
guard
guard ... else {...}
如果解析错误,执行else,而不是抛出异常
KeyPath
https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#grammar_key-path-expression
https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#grammar_key-path-string-expression
Swift4新特性
语法:\Type.property.property....
#keyPath(…) 用于objectc
\type name.path 最终编译生成一个KeyPath类型, 实例可接受一个keyPath参数:
struct SomeStructure {
var someValue: Int
}
let s = SomeStructure(someValue: 12)
let pathToProperty = \SomeStructure.someValue
let value = s[keyPath: pathToProperty]
// value is 12
.self 表示整个实例本身
省略Type时,表示要应用的类型自身
KeyPath泛型参数有两个,一个表示类型,一个表示返回值
@escaping
https://docs.swift.org/swift-book/LanguageGuide/Closures.html -> 搜索@Escaping
逃逸闭包是指:闭包作为一个参数传递给函数,但是在函数返回之后才执行。
比如,需要网络IO函数使用闭包作为回调函数。这种情况下,必须使用@escaping标注闭包,同时,原来的闭包必须明确引用self,而不能直接引用属性名。
protocol
protocol只能作为泛型约束,不能像Java那样作为类型名约束变量类型。