从Swift的属性包装器中,您可以有人引用拥有被包装属性的类实例或被删除的实例吗?使用self显然不起作用,也不起作用super。
我试图传递self给属性包装器,init()但这也不起作用,因为self在评估Configuration时on 尚未定义@propertywrapper。
我的用例在用于管理大量设置或配置的类中。如果有任何属性更改,我只想通知感兴趣的人某些更改。他们实际上并不需要只知道哪个值,因此实际上不必为每个属性使用KVO或Publisher。
属性包装器看起来很理想,但是我不知道如何传递对包装器可以回调的拥有实例的某种引用。
参考文献:
enum PropertyIdentifier {
case backgroundColor
case textColor
}
@propertyWrapper
struct Recorded<T> {
let identifier:PropertyIdentifier
var _value: T
init(_ identifier:PropertyIdentifier, defaultValue: T) {
self.identifier = identifier
self._value = defaultValue
}
var value: T {
get { _value }
set {
_value = newValue
// How to callback to Configuration.propertyWasSet()?
//
// [self/super/...].propertyWasSet(identifier)
}
} …Run Code Online (Sandbox Code Playgroud) 组合订阅示例代码片段全部将生成的订阅存储到集合subscriptions中
private var subscriptions = Set<AnyCancellable>()
Run Code Online (Sandbox Code Playgroud)
为什么我们需要这样做?
future
.sink(receiveCompletion: { print($0) }, receiveValue: { print($0) })
.store(in: &subscriptions)
Run Code Online (Sandbox Code Playgroud) 不知道是否有一个优秀的文档来展示Combine和RxSwift之间的区别?
快速学习对我来说有好处,Combine因为我已经对这方面有了很好的了解RxSwift
这是我第一次使用 AppKit 和NSTableView. 它由NSFetchedResultsController核心数据支持。当数据集发生更改时,Notification将发送:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
guard let links = self.fetchedResultsController.fetchedObjects else {
return
}
if self.viewContext.hasChanges {
try? self.viewContext.save()
}
self._links = links
NotificationCenter.default.post(name: .reloadLinkList, object: nil)
}
Run Code Online (Sandbox Code Playgroud)
NotificationCenter.default.publisher(for: .reloadLinkList).receive(on: RunLoop.main).sink { notification in
self.list.tableView.reloadData()
self.list.linksModel.selectedRows = IndexSet([])
}
.store(in: &cancellables)
Run Code Online (Sandbox Code Playgroud)
这对于插入和更新数据非常有用。当我尝试删除某些内容时,我得到:
Thread 1: Fatal error: UnsafeRawBufferPointer with negative count
Run Code Online (Sandbox Code Playgroud)
删除选定对象的代码如下:
Thread 1: Fatal error: UnsafeRawBufferPointer with negative count …Run Code Online (Sandbox Code Playgroud) .collectSwift 的组合中的操作将在哪个线程上发出预期的线程?
具体来说,我在第二个前提条件中看到此代码崩溃,但在第一个前提条件中没有崩溃:
return Publishers.MergeMany(publishers)
.handleEvents(receiveOutput: { _ in
precondition(Thread.isMainThread) // <- This is fine
})
.collect()
.handleEvents(receiveOutput: { _ in
precondition(Thread.isMainThread) // <- Crash is here
})
Run Code Online (Sandbox Code Playgroud)
就好像该.collect操作正在选择一个不同的线程来使用,即使最终的发布者必须MergeMany在主线程上发出。我通过从 Firebase 上传的崩溃日志推断出此行为。谁能解释这种观察到的行为?
我知道发布者通常比闭包更强大,但是我想询问并讨论一个具体的例子:
func getNotificationSettingsPublisher() -> AnyPublisher<UNNotificationSettings, Never> {
let notificationSettingsFuture = Future<UNNotificationSettings, Never> { (promise) in
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
promise(.success(settings))
}
}
return notificationSettingsFuture.eraseToAnyPublisher()
}
Run Code Online (Sandbox Code Playgroud)
我认为这是 Future 发布者的一个有效示例,可以在这里使用它而不是使用完成处理程序。让我们用它做点什么:
func test() {
getNotificationSettingsPublisher().sink { (notificationSettings) in
// Do something here
}
}
Run Code Online (Sandbox Code Playgroud)
这有效,但是它会告诉我 sink ( AnyCancellable)的结果未使用。因此,每当我尝试获取一个值时,我都需要存储可取消对象或分配它,直到我获得一个值。
是否有类似 sinkOnce 或可取消项的自动销毁之类的东西?有时我不需要取消的任务。但是我可以这样做:
func test() {
self.cancellable = getNotificationSettingsPublisher().sink { [weak self] (notificationSettings) in
self?.cancellable?.cancel()
self?.cancellable = nil
}
}
Run Code Online (Sandbox Code Playgroud)
所以一旦我收到一个值,我就会取消订阅。(我猜我可以在水槽的完成关闭中做同样的事情)。
这样做的正确方法是什么?因为如果我使用一个闭包,它会被调用多少次函数被调用,如果它只被调用一次,那么我不需要取消任何东西。
你会说普通的完成处理程序可以用组合代替吗?如果是这样,你会如何处理接收一个值然后取消?
最后但并非最不重要的是,调用完成,我还需要取消订阅吗?我至少需要更新可取消并将其设置为 nil 对吗?我假设将订阅存储在一个集合中是为了长期运行的订阅,但是单值订阅呢?
谢谢
let myPassthrough = PassthroughSubject<String, Error>()
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用以下方法向传递主题发送值send:
myPassthrough.send("abc")
Run Code Online (Sandbox Code Playgroud)
我如何发送失败?
我试过:
myPassthrough.send(Fail(error: error))
myPassthrough.send(completion: Fail(error: error))
myPassthrough.send(completion: Just(error))
myPassthrough.send(completion: error)
Run Code Online (Sandbox Code Playgroud)
他们都没有编译
所以我有一个 type 值AnyPublisher<Foo, Error>,我需要将其转换为Published<Foo>.Publisher这样我可以将其用作@Published
所以我的想法是我有一个 MVVM 架构
struct SwiftUIView: View {
@ObservedObject var viewModel: MyViewModel
var body: some View {
Text(/*Foo has a title, how do I access it? */)
}
}
class MyViewModel: ObservableObject {
var cellModels: AnyPublisher<Foo, Error>
// so the idea is to have and then access it in swiftUI view via viewModel.cellModels2.title
@Published cellModels2 = convert_somehow_to_publisher(cellModels)
}
Run Code Online (Sandbox Code Playgroud)
显然我不能使用 viewModel.cellModels
那可能吗?
我有以下代码,但收到消息错误:
“wrappedValue”不可用:@Published 仅适用于类的属性
//*
/**
Chat
Created on 29/07/2020
*/
import SwiftUI
let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0)
struct ConnectionView: View {
@ObservedObject var keyboardResponder = KeyboardResponder()
@ObservedObject var viewModel = ConnectionVM()
// @State var uuid1: String = ""
// @State var uuid2: String = ""
@State var authenticationDidFail: Bool = false
var body: some View {
return VStack {
WelcomeText()
LogoImage()
UUIDTextField(uuid: viewModel.uuid1)
UUIDTextField(uuid: viewModel.uuid2)
if authenticationDidFail {
Text("Information not correct. Try again.")
.offset(y: …Run Code Online (Sandbox Code Playgroud) 一个ViewModel类有一个sourceProperty正在由 编辑的TextField。该属性是@Published. 我想将它Logic传递给具有Binding<String>. 该类将监听更改sourceProperty,对其做出反应并将其输出设置为属性@Published output。
如何@Published sourceProperty作为初始化参数传递给类Logic?
相关代码:
final class ViewModel {
@Published var sourceProperty: String = ""
private var logic: Logic?
init() {
self.logic = Logic(data: $sourceProperty)
$logic.output.sink({result in
print("got result: \(result)")
})
}
}
final class Logic: ObservableObject {
private var bag = Set<AnyCancellable>()
@Published var output: String = ""
@Binding var data: String
init(data: Binding<String>) {
self._data …Run Code Online (Sandbox Code Playgroud)