-
Notifications
You must be signed in to change notification settings - Fork 0
/
Contents.swift
380 lines (275 loc) · 8.96 KB
/
Contents.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/// # Features introduced with Swift 5.1
import UIKit
/** # SE-0255 Implicit returns from single-expression functions
https://github.com/apple/swift-evolution/blob/master/proposals/0255-omit-return.md
*/
func makeDouble() -> Double {
3.0 // new
// return 3.0 // old
}
var double: Double {
24.0
}
print(makeDouble())
print(double)
/** # SE-0068 Expanding Swift Self to class members and value types (Universal Self)
https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
*/
struct MyStruct {
static func staticMethod() {}
func instanceMethod() {
Self.staticMethod() // new
MyStruct.staticMethod() // old
type(of: self).staticMethod()
}
}
// Inheritance
class UsersManager {
class var maxUsersCount: Int { 5 }
static func printMaxUsersCount() {
print(Self.maxUsersCount) // new
// print(UsersManager.maxUsersCount) // old
}
}
class ShopClientManager: UsersManager {
override class var maxUsersCount: Int { 1 }
}
UsersManager.printMaxUsersCount() // 5
ShopClientManager.printMaxUsersCount() // 1
/** #SE-0254 Static and class subscripts
https://github.com/apple/swift-evolution/blob/master/proposals/0254-static-subscripts.md
*/
enum IntToString {
static var values: [Int: String] = [
0: "Zero",
1: "One",
2: "Two"
]
static subscript(_ number: Int) -> String {
get { values[number] ?? "A lot" }
set { values[number] = newValue }
}
}
print(IntToString[1])
IntToString[3] = "Three"
print(IntToString[3]) // 3.0
/// # Warnings for ambiguous none cases
enum BorderStyle {
case solid(thickness: Int)
case dotted
case none
}
let border: BorderStyle? = .none // warning ->
/// # Matching optional enums against non-optionals
switch border { // new
case .solid: break
case .dotted: break
case .some(.none): break
case .none: break
}
switch border { // old
case .some(.solid): break
case .some(.dotted): break
case .some(.none): break
case .none: break
}
/** # SE-0244 Opaque Result Types
A function or method with an opaque return type hides its return value’s type information. It lets you keep your implementation details private.
https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md
https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html
*/
// Protocols with Self or associated type requirements (`some` )
func makeInt() -> some Equatable {
Int.random(in: 1...10)
}
makeInt() == makeInt()
protocol APIRequest {
var endpoint: String { get }
func perform() -> String
}
extension APIRequest {
func perform() -> String {
"Performing request to endpoint \(endpoint)"
}
}
protocol Initializable {
init() // for generic examples
}
struct LoginRequest: APIRequest, Initializable {
let endpoint: String = "/login"
}
struct UpdateUserRequest: APIRequest, Initializable {
let endpoint: String = "/putUser"
}
func makeRequest() -> some APIRequest {
return LoginRequest()
// Invalid:
// if true {
// return LoginRequest()
// }
// return UpdateUserRequest()
}
let req1 = makeRequest() // function implementation decides about return type
// On the other hand - generic approach
func genericMakeRequest<T: APIRequest & Initializable>() -> T {
return T()
}
let req2: UpdateUserRequest = genericMakeRequest() // caller decides about return type
let req3: LoginRequest = genericMakeRequest()
/// **Hide implementation details**
struct DoubleRequest<T: APIRequest, U: APIRequest>: APIRequest {
var req1: T
var req2: U
let endpoint: String
init(req1: T, req2: U) {
endpoint = ""
self.req1 = req1
self.req2 = req2
}
func perform() -> String {
"\(req1.perform()) \(req2.perform())"
}
}
func makeDoubleRequest<T: APIRequest, U: APIRequest>(_ req1: T, _ req2: U) -> some APIRequest {
let request = DoubleRequest(req1: req1, req2: req2) // Type is DoubleRequest<T, U>
return request // This underlying concrete type is hidden
}
let doubleRequest = makeDoubleRequest(req1, req2) // req1 is `some APIRequest`, req2 is `UpdateUserRequest`. Result is `some APIRequest`
let tripleRequest = makeDoubleRequest(doubleRequest, req3) // req3 is `LoginRequest`
/** # SE-0240 Ordered Collection Diffing
https://github.com/apple/swift-evolution/blob/master/proposals/0240-ordered-collection-diffing.md
Calculates the differences between two ordered collections – what items to remove and what items to insert. Used with any ordered collection that contains Equatable elements
*/
let scores1 = [100, 101, 102]
let scores2 = [100, 101, 202, 203]
let diff = scores2.difference(from: scores1)
print(diff)
dump(diff)
print(scores1.applying(diff)! == scores2) // true
var scores3 = scores1
// apply diff manually
for change in diff {
switch change {
case .remove(let offset, _, _):
scores3.remove(at: offset)
case .insert(let offset, let element, _):
scores3.insert(element, at: offset)
}
}
print(scores3)
/** # SE-0245 Add an Array Initializer with Access to Uninitialized Storage
https://github.com/apple/swift-evolution/blob/master/proposals/0245-array-uninitialized-initializer.md
*/
let randomNumbers = Array<Int>(unsafeUninitializedCapacity: 10) { buffer, initializedCount in
for x in 0..<10 {
buffer[x] = Int.random(in: 0...10)
}
initializedCount = 10
}
let randomNumbers2 = (0...9).map { _ in Int.random(in: 0...10) }
//easier to read, but less efficient
/** # SE-0258 Property Wrappers
https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md
automatically wrap property values using specific types
*/
@propertyWrapper
class Capitalized {
private(set) var value: String
var wrappedValue: String {
get { return value.capitalized }
set { value = newValue }
}
init(wrappedValue: String) {
self.value = wrappedValue
}
}
/** # SE-0242 Synthesize default values for the memberwise initializer
https://github.com/apple/swift-evolution/blob/master/proposals/0242-default-values-memberwise.md
*/
struct User {
@Capitalized var name: String
var postsCount: Int = 0 // must be `var`
}
let noob = User(name: "newbie")
let bodhisattva = User(name: "1337-man", postsCount: 9999)
print(noob.name) // "Newbie"
/// Example `UserDefault` property wrapper
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get {
return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}
let a = UserDefault(key: "FOO_FEATURE_ENABLED", defaultValue: false)
enum GlobalSettings {
@UserDefault(key: "FOO_FEATURE_ENABLED", defaultValue: false)
static var isFooFeatureEnabled: Bool
@UserDefault(key: "BAR_FEATURE_ENABLED", defaultValue: false)
static var isBarFeatureEnabled: Bool
}
/** # SE-0261 Identifiable Protocol
https://github.com/apple/swift-evolution/blob/master/proposals/0261-identifiable.md
public protocol Identifiable {
/// A type representing the stable identity of the entity associated with `self`.
associatedtype ID : Hashable
/// The stable identity of the entity associated with `self`.
var id: Self.ID { get }
}
extension Identifiable where Self: AnyObject {
var id: ObjectIdentifier {
return ObjectIdentifier(self)
}
}
*/
class ClassWithID: Identifiable {}
let classWithID = ClassWithID()
print(classWithID.id)
/** # SE-XXXX Function builders (draft proposal)
* https://github.com/apple/swift-evolution/blob/9992cf3c11c2d5e0ea20bee98657d93902d5b174/proposals/XXXX-function-builders.md
* https://blog.vihan.org/swift-function-builders/
* Function builers sound like they create functions but they can create any value.
A function builders is something you can attach to a class which makes it easier to produce an object that is composed of more objects
*/
@_functionBuilder
class UIViewFunctionBuilder {
static func buildBlock(_ children: UIView...) -> UIView {
let newView = UIView()
for view in children {
newView.addSubview(view)
}
return newView
}
}
func MakeLabel(with text: String) -> UILabel {
let label = UILabel()
label.text = text
return label
}
@UIViewFunctionBuilder
func buildView() -> UIView {
MakeLabel(with: "Hello, World!")
MakeLabel(with: "My name is John Doe!")
}
let view: UIView = buildView()
/** # Swift 5.1 features behind SwiftUI
*/
import SwiftUI
struct ContentView: View {
var body: some View { // Opaque Result Type
// print("aaa")
/*return*/ Text("Hello World") // Implicit returns from single-expression functions, Function builder
}
}
/**
Sources:
* https://swift.org/blog/swift-5-1-released/
* https://www.hackingwithswift.com/articles/182/whats-new-in-swift-5-1
* https://www.swiftbysundell.com/articles/the-swift-51-features-that-power-swiftuis-api/
*/