associatedtype
associatedtype用于在protocol中代指一个确定类型并要求该类型实现指定方法
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// conformance to the Container protocol
typealias Item = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
where
where语句可以用来设置约束条件、限制类型,让代码更加简洁、易读。
-
可以使用 where 关键词在 switch、for in 语句上做些条件限制。
for score in scores where score >= 90 {}
-
在 do catch 里面使用。
enum ExceptionError:Error{ case httpCode(Int) } func throwError() throws { throw ExceptionError.httpCode(500) } do{ try throwError() }catch ExceptionError.httpCode(let httpCode) where httpCode >= 500{ print("server error") }catch { print("other error") }
-
与协议结合来设置限制类型。
-
在 associatedtype 后面声明的类型后追加 where 约束语句。
protocol Sequence { associatedtype Element where Self.Element == Self.Iterator.Element //它限定了 Sequence 中 Element 这个类型必须和 Iterator.Element 的类型一致 }
-
Sequence
序列的一切功能都是建立在 Sequence
协议之上,定义了map,filter,forEach,dropFirst,flatMap等方法。
序列有两个特性:1. 它的容量可以有限也可无限,2. 只可以迭代 (iterate) 一次。
protocol Sequence {
associatedtype Iterator: IteratorProtocol
func makeIterator() -> Iterator
}
序列协议有两个组成部分。一个是一个关联类型 (associated type),也就是这个 Iterator
(迭代器)。这个关联类型必须要遵循 IteratorProtocol 协议;另一个组成部分是一个函数,它能够为我们构建 Iterator
,这个函数返回的类型必须与我们声明的 Iterator
类型相同。
IteratorProtocol
协议看起来与 Sequence
协议类似。它有一个关联类型 Element
,这个 Element
就是迭代器所声明的类型,或者说是需要迭代的类型;此外它还有一个名为 next
的函数,它会返回序列的下一个元素并对迭代器本身进行修改 (mutate)。
protocol IteratorProtcol {
associatedtype Element
mutating func next() -> Element?
}
-
Collection
: -
BidirectionalCollection
: 继承自Collection
,但是双向集合可以向两个方向任意移动。在集合当中,已经有了indexAfter
这个函数,所以为了增加后退的功能,添加了一个indexBefore
的函数,它将可以让我们以相反的顺序来遍历集合。 -
RandomAccessCollection
:可以更快地访问值。您可以直接跳转到想要获取的那个元素,而不必去逐步遍历。 -
RangeReplaceableCollection
:允许您使用其它内容来将集合中间的某个部分替换掉。 -
MutableCollection
:允许您对这些值进行读取或修改。
indirection
用来声明递归枚举,告诉编译器插入必要的间接层。
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}
@objcMembers
如果只想公开一个方法或属性,可以使用@objc属性标记该方法。然而,如果你想让类中的所有方法都暴露给Objective-C,可以使用一个快捷方式:@objcMembers关键字,@objc 相对于@objcMembers 而言,可能会增大包的编译大小。
@objcMembers class MyController: UIViewController {
//login()方法将自动暴露给Objective-C,就像它被标记为@objc一样,因为它所在的整个类被标记为@objcMembers
func login() {
}
}
.Type
.Type 表示的是某个类型的元类型,元类型就是类型的类型。而在 Swift 中,除了 class
,struct
和 enum
这三个类型外,我们还可以定义 protocol
。对于 protocol
来说,有时候我们也会想取得接口的元类型。这时我们可以在某个 protocol
的名字后面使用 .Protocol 来获取,使用的方法和 .Type 是类似的。
The metatype of a class, structure, or enumeration type is the name of that type followed by .Type. The metatype of a protocol type—not the concrete type that conforms to the protocol at runtime—is the name of that protocol followed by .Protocol. For example, the metatype of the class type
SomeClass
isSomeClass.Type
and the metatype of the protocolSomeProtocol
isSomeProtocol.Protocol
.
.self
获得元类型的值。当我们访问静态变量或静态函数的时候其实也是通过元类型访问的,只是 Xcode 帮我们省略了 .self。
You can use the postfix self expression to access a type as a value. For example, SomeClass.self returns SomeClass itself, not an instance of SomeClass. And SomeProtocol.self returns SomeProtocol itself, not an instance of a type that conforms to SomeProtocol at runtime. You can use a type(of:) expression with an instance of a type to access that instance’s dynamic, runtime type as a value, as the following example shows:
Easy example
struct Something {
var x = 5
}
let a = Something()
type(of:a) == Something.self // true
Hard example
class BaseClass {
class func printClassName() {
print("BaseClass")
}
}
class SubClass: BaseClass {
override class func printClassName() {
print("SubClass")
}
}
let someInstance: BaseClass = SubClass()
/* | |
compileTime Runtime
| |
To extract, use: .self type(of)
The compile-time type of someInstance is BaseClass,
and the runtime type of someInstance is SubClass */
type(of: someInstance) == SubClass.self // TRUE
type(of: someInstance) == BaseClass.self // FALSE
网友评论