funcloadDashboardData(completion: @escaping (DashboardData?) -> Void) { let group =DispatchGroup() var user: User? var orders: [Order]? var error: Error? group.enter() fetchUser { result in user =try? result.get() group.leave() } group.enter() fetchOrders { result in orders = (try? result.get()) ?? [] group.leave() } group.notify(queue: .main) { iflet u = user, let o = orders { completion(DashboardData(user: u, orders: o)) } else { completion(nil) } } }
let uploadQueue =OperationQueue() uploadQueue.maxConcurrentOperationCount =3 for chunk in chunks { let op =BlockOperation { uploadChunk(chunk) } uploadQueue.addOperation(op) } uploadQueue.waitUntilAllOperationsAreFinished() mergeChunks()
10.3 搜索防抖
用户输入时,取消上一次未完成的搜索任务,延迟 300ms 再发起新请求:
1 2 3 4 5 6 7 8 9
var searchWorkItem: DispatchWorkItem? funcsearchTextDidChange(_text: String) { searchWorkItem?.cancel() let workItem =DispatchWorkItem { [weakself] in self?.performSearch(text) } searchWorkItem = workItem DispatchQueue.main.asyncAfter(deadline: .now() +0.3, execute: workItem) }
assert(Thread.isMainThread, "UI must be updated on main thread")
11.2 避免循环引用
在闭包中使用 self 时注意 [weak self]:
1 2 3 4 5 6 7
DispatchQueue.global().async { [weakself] in guardletself=selfelse { return } let result =self.doWork() DispatchQueue.main.async { [weakself] in self?.updateUI(result) } }
// 获取成员变量 Ivar *ivars = class_copyIvarList(cls, &count); for (unsignedint i = 0; i < count; i++) { Ivar ivar = ivars[i]; constchar *name = ivar_getName(ivar); constchar *type = ivar_getTypeEncoding(ivar); }
5.4 动态创建类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 创建新类 Class newClass = objc_allocateClassPair([NSObjectclass], "MyDynamicClass", 0);
let searchAction =Action<String, [User], NSError> { keyword in return searchAPI(keyword) // 返回 SignalProducer }
// 绑定启用条件(例如:输入非空) let enabledSearch =Action(state: viewModel.keyword, enabledIf: { $0.count >0 }) { _, keyword in return searchAPI(keyword) }
// 执行 searchAction.apply("Swift").startWithResult { result in switch result { case .success(let users): self.users = users case .failure(let error): self.showError(error) } }
五、常用操作符
5.1 转换类
map:转换每个值
1 2 3
signal .map { $0.uppercased() } .observeValues { print($0) }
filter:过滤值
1 2 3
signal .filter { $0.count >=3 } .observeValues { print($0) }
reduce:聚合为单个值(在 completed 时发出)
1 2 3
signal .reduce(0) { $0+$1 } .observeValues { print("总和: \($0)") }
5.2 组合类
combineLatest:合并多个流的最新值
1 2 3 4
let combined =Signal.combineLatest(usernameSignal, passwordSignal) combined.observeValues { (user, pwd) in loginButton.isEnabled = user.count >0&& pwd.count >=6 }
zip:按顺序一一配对
1 2
let zipped =Signal.zip(numbersSignal, lettersSignal) // (1,A), (2,B), (3,C)...
5.3 扁平化 (flatten)
merge:内层多个流的值按到达顺序全部输出
concat:按顺序消费内层流,前一个完成后才订阅下一个
latest:只保留「最新」的内层流,常用于搜索联想(新关键词来时取消旧请求)
1 2 3 4 5 6 7
searchKeywordSignal .flatMap(.latest) { keyword in searchAPI(keyword) // 新关键词会取消上一次请求 } .observeValues { users in self.updateUI(users) }