按照Foo2类示例,我曾经将我的对象作为ObservableObject,我可以设置一个@Published值并监听它们的更改,就像使用合并一样。
现在我正在使用示例@Observable中所示的宏Foo1,我无法创建类似管道的组合。
@Observable有没有一种方法可以像我在使用@Published对象中的宏值时使用的方式来监听宏值ObservableObject?
@Observable class Foo1 {
var isEnabled = false
init() {
isEnabled
.map { $0 } // Error: Value of type 'Bool' has no member 'map'
}
}
class Foo2: ObservableObject {
@Published var isEnabled = false
var cancellables = Set<AnyCancellable>()
init() {
$isEnabled
.map { $0 } // Works like a charm
.sink { print($0.description) }
.store(in: &cancellables)
}
}
Run Code Online (Sandbox Code Playgroud) 每次 atextField的值更改时,我都尝试执行一个操作。
@Published var value: String = ""
var body: some View {
$value.sink { (val) in
print(val)
}
return TextField($value)
}
Run Code Online (Sandbox Code Playgroud)
但我得到以下错误。
无法将“已发布”类型的值转换为预期的参数类型“绑定”
我有一个简单的主/细节界面,其中细节视图修改数组中的一个项目。使用以下内容,模型已正确更新,但 SwiftUI 不会刷新视图以反映更改。
模型:
struct ProduceItem: Identifiable {
let id = UUID()
let name: String
var inventory: Int
}
final class ItemStore: BindableObject {
var willChange = PassthroughSubject<Void, Never>()
var items: [ProduceItem] { willSet { willChange.send() } }
init(_ items: [ProduceItem]) {
self.items = items
}
}
Run Code Online (Sandbox Code Playgroud)
显示 ProduceItems 列表的主视图(一个 ItemStore 被插入到 SceneDelegate 的环境中):
struct ItemList: View {
@EnvironmentObject var itemStore: ItemStore
var body: some View {
NavigationView {
List(itemStore.items.indices) { index in
NavigationLink(destination: ItemDetail(item: self.$itemStore.items[index])) {
VStack(alignment: .leading) { …Run Code Online (Sandbox Code Playgroud) 我们的应用程序支持iOS 11及更高版本。在iOS 13中,我们使用SwiftUI+Combine
我们用相应的check 或包裹导入SwiftUI或Combine框架。如果我们在iOS 12下从Xcode 11运行我们的应用程序,则会出现错误#if canImport(SwiftUI)#if canImport(Combine)dyld: Library not loaded: /System/Library/Frameworks/Combine.framework/Combine
我们通过可选地链接来解决SwiftUI的相同问题。
但是我们无法为Combine设置相同的名称,因为甚至无法选择它进行链接
我正在尝试实现类似于下面介绍的场景的东西(创建 URL,请求服务器,解码 json,在自定义NetworkError枚举中包装的每个步骤上都出错):
enum NetworkError: Error {
case badUrl
case noData
case request(underlyingError: Error)
case unableToDecode(underlyingError: Error)
}
//...
func searchRepos(with query: String, success: @escaping (ReposList) -> Void, failure: @escaping (NetworkError) -> Void) {
guard let url = URL(string: searchUrl + query) else {
failure(.badUrl)
return
}
session.dataTask(with: url) { data, response, error in
guard let data = data else {
failure(.noData)
return
}
if let error = error {
failure(.request(underlyingError: error))
return
}
do {
let repos …Run Code Online (Sandbox Code Playgroud) 在RxSwift中,很容易将a Driver或Observablein 绑定到a View Model中的某个观察者ViewController(即UILabel)。
我通常更喜欢用其他可观察变量创建的可观察变量建立一个管道,而不是“强制”推送值(例如通过a PublishSubject)。
让我们使用此示例:从网络中获取一些数据后更新aUILabel
final class RxViewModel {
private var dataObservable: Observable<Data>
let stringDriver: Driver<String>
init() {
let request = URLRequest(url: URL(string:"https://www.google.com")!)
self.dataObservable = URLSession.shared
.rx.data(request: request).asObservable()
self.stringDriver = dataObservable
.asDriver(onErrorJustReturn: Data())
.map { _ in return "Network data received!" }
}
}
Run Code Online (Sandbox Code Playgroud)
final class RxViewController: UIViewController {
private let disposeBag = DisposeBag()
let rxViewModel = RxViewModel() …Run Code Online (Sandbox Code Playgroud) 在 Combine 框架中,我们可以Error在使用tryMap.
但是,我们如何才能更具体地了解Error类型?
例如,
let publisher = urlSession.dataTaskPublisher(for: request).tryMap { (data, response) -> (Data, HTTPURLResponse) in
guard let response = response as? HTTPURLResponse else {
throw URLError(.cannotParseResponse)
}
return (data, response)
}
Run Code Online (Sandbox Code Playgroud)
如何指定Errorthis的类型publisher?我想使用URLError而不是Error.
我setFailureType(to:)在Combine框架中找到了方法。但是,它不适用于tryMap(_:).
我正在尝试使用 Swift Combine 来获取属性的更改事件。
我有这个发布isLogged属性的类
class CurrentUser: Account {
static let me = CurrentUser() //Singleton
@Published var isLogged: Bool = false
}
Run Code Online (Sandbox Code Playgroud)
从发布该profileImageVersion属性的另一个类继承
class Account {
@Published var profileImageVersion: String?
init(){
self.profileImageVersion = ""
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试订阅已发布的继承profileImageVersion属性,但没有成功!
// Subscribe to account image changes
userImageChangedSubscriber = CurrentUser.me.$profileImageVersion.receive(on: DispatchQueue.main).sink(receiveValue: { (imageVersion) in
...
}
})
Run Code Online (Sandbox Code Playgroud)
错误是 Fatal error: Call of deleted method
另一方面,如果我订阅了该isLogged属性,则一切正常...
// Subscribe to logged changes
userLoggedSubscriber = CurrentUser.me.$isLogged.receive(on: DispatchQueue.main).sink(receiveValue: { (logged) …Run Code Online (Sandbox Code Playgroud) 我认为此错误消息是 Xcode 12 中的 SwiftUI 的新消息,因为它在 Google 中的点击率为 0,而该消息本身相当通用:
在安装在 View 之外访问 State 的值。这将导致初始值的常量绑定并且不会更新。
我有以下代码(删除了一些绒毛):
public struct ContentView: View {
@ObservedObject var model: RootViewModel
public var body: some View {
VStack(alignment: .center, content: {
Picker(selection: model.$amount, label: Text("Amount")) {
Text("€1").tag(1)
Text("€2").tag(2)
Text("€5").tag(5)
Text("€10").tag(10)
}.pickerStyle(SegmentedPickerStyle())
Text("Donating: €\(model.amount)").font(.largeTitle)
}).padding(.all, 20.0)
}
}
public class RootViewModel: ObservableObject {
@State public var amount: Int = 1
}
Run Code Online (Sandbox Code Playgroud)
我曾经有field权利,ContentView而且工作正常。现在 UI 不再更新,而是我收到了运行时警告。
这是关于 SwiftUI 和架构的一般性问题,所以我将举一个简单但有问题的例子。
我有一个View显示 s 列表的第一个Item。该列表由一个类(我在这里称之为)管理ListViewModel。在第二个视图中,我可以修改其中之一Item,并使用“保存”按钮保存这些修改。在简化版本中,我可以使用 轻松完成此操作@Binding。感谢 SwiftUI:
struct ListView: View {
@StateObject var vm = ListViewModel()
var body: some View {
NavigationView {
List(Array(vm.data.enumerated()), id: \.1.id) { index, item in
NavigationLink(destination: DetailView(item: $vm.data[index])) {
Text(item.name)
}
}
}
}
}
struct DetailView: View {
@Binding var initialItem: Item
@State private var item: Item
init(item: Binding<Item>) {
_item = State(initialValue: item.wrappedValue)
_initialItem = item
}
var body: some View …Run Code Online (Sandbox Code Playgroud)