【问题标题】:Type of expression is ambiguous without more context error SwiftUI表达式类型不明确,没有更多上下文错误 SwiftUI
【发布时间】:2020-02-19 11:44:14
【问题描述】:

我制作了一个带有标题和 neumorphic 按钮的 Neumorphic 样式视图。当我在预览代码中打开暗模式时,视图会发生变化。 然后我决定做一个开关来打开或关闭暗模式。不幸的是,我还没有找到一种方法来赋予切换功能(但它不应该产生任何错误),我得到了这个错误。我之前有一个完整的 Neumorphic 风格结构,这就是为什么你可能会看到你不知道的术语。当我移除切换开关时,错误消失了。

struct ContentView: View {

    @Environment(\.colorScheme) private var colorScheme
    @State private var isToggle : Bool = false

    var body: some View {

        ZStack {
            VStack {

                Text("Neumorphism") <- Type of expression is ambiguous without more context
                    .font(.system(size: 32,
                                  weight: .bold,
                                  design: .rounded))
                    .padding(20)

                Button("Hello world", action: { })
                    .padding(20)

            }
            .frame(minWidth: 0, maxWidth: .infinity,
                   minHeight: 0, maxHeight: .infinity,
                   alignment: .center)
                .background(backgroundColor)
                .buttonStyle(NeumorphicButtonStyle(colorScheme: colorScheme))
                .edgesIgnoringSafeArea(.all)

            Toggle(isOn: $isToggle) {
                 Text("Dark Mode") <- How could I make this turn on and off dark mode?

            }
        }

    }
    var backgroundColor: Color {
        switch colorScheme {
        case .light: return NeumorphicButtonStyle.Appearance().lightColor
        case .dark: return NeumorphicButtonStyle.Appearance().darkColor
        @unknown default: return NeumorphicButtonStyle.Appearance().lightColor
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.colorScheme, .light)
    }
}

【问题讨论】:

  • 没有观察到错误(当移除不可用的 NeumorphicButtonStyle 相关部分时)。使用 Xcode 11.2 / iOS 13.2 测试。

标签: swift xcode compiler-errors swiftui


【解决方案1】:

我强烈建议将视图和视图的逻辑分开。一种常见的方法是MVVM 概念。我在下面的例子中加入了这个概念(用 Xcode 11.3.1 测试):

import SwiftUI
import Combine

final class ContentViewModel: ObservableObject {
    @Published var darkModeActivated: Bool
    @Published var backgroundColor: Color

    private var sink: AnyCancellable?

    init() {
        self.darkModeActivated = false
        self.backgroundColor = Color.white

        self.sink = self.$darkModeActivated.sink() { value in
            if value {
                self.backgroundColor = Color.black
            } else {
                self.backgroundColor = Color.white
            }
        }
    }

    public func toggleDarkmode() {
        self.darkModeActivated.toggle()
    }
}

struct ContentView: View {
    @ObservedObject var viewModel: ContentViewModel

    var body: some View {
        ZStack {
            VStack {
                Text("Neumorphism")
                    .font(.system(size: 32,
                                  weight: .bold,
                                  design: .rounded))
                    .padding(20)

                Button("Hello world", action: { self.viewModel.toggleDarkmode() })
                    .padding(20)
                Button("Hello world2", action: { self.viewModel.darkModeActivated.toggle() })
                    .padding(20)

            }
            .frame(minWidth: 0, maxWidth: .infinity,
                   minHeight: 0, maxHeight: .infinity,
                   alignment: .center)
                .background(self.viewModel.backgroundColor)
                .edgesIgnoringSafeArea(.all)

            Toggle(isOn: self.$viewModel.darkModeActivated) {
                 Text("Dark Mode")
            }
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(viewModel: .init())
            .environment(\.colorScheme, .light)
    }
}

在示例中,视图直接绑定变量darkModeActivated 来设置切换按钮的状态,backgroundColor 来存储背景颜色。简单地说,如果您从视图中更改变量的值,您可以在self.$viewModel.darkModeActivated 中使用$ 前缀。可以在here找到全面的解释。如果状态更改完全由 ViewModel 处理,会发生什么逻辑。

上面示例中最困难的部分显然是在darkModeActivated 的值发生变化时得到通知。因此,我按照here 的建议使用了 Combine 框架来附加订阅者。

使用普通按钮激活暗模式也很容易。只需从按钮的操作闭包中调用 ViewModel 函数。或者像上面的例子一样直接切换值。

【讨论】:

  • 这太完美了!效果很好。您认为我如何将其合并到按钮本身中?
  • “进入按钮本身”是什么意思?您希望您的“Hello World”按钮具有类似的行为吗?
  • 是的,所以每次我点击按钮时,它都会切换颜色模式,就像拨动开关一样。
  • 这很容易。我在上面的答案中编辑了示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
相关资源
最近更新 更多