Swiftui ViewModifier должен явно принять тему или прочитать ее из среды - почему какой -либо протокол терпит неудачу?IOS

Программируем под IOS
Ответить
Anonymous
 Swiftui ViewModifier должен явно принять тему или прочитать ее из среды - почему какой -либо протокол терпит неудачу?

Сообщение Anonymous »

У меня есть система базовой темы протокола, которую я использую в своем приложении. Хотя это работает нормально в целом, я пришел к проблеме при попытке создать ViewModifier < /code>, который принимает параметр темы и применяет его значения к представлению.struct ThemedModifier: ViewModifier {
let theme: Theme?
@Environment(\.appTheme) private var envTheme

func body(content: Content) -> some View {
guard let theme = theme ?? (envTheme as? Theme) else {...}

let font = theme.text.font
let textColor = theme.text.primaryColor

return AnyView(
content
.font(font)
.foregroundColor(textColor)
)
}
}

extension View {
func themed(_ theme: Theme? = nil) -> some View {
modifier(ThemedModifier(theme: theme))
}
}

struct ContentView: View {
@Environment(\.appTheme) private var theme

var body: some View {
// ERROR: Type 'any ThemeProtocol' cannot conform to 'ThemeProtocol'
Text("Hello, Modifier external!")
.themed(theme)
}
}

Вопрос
Что мне нужно изменить, чтобы модификатор мог принять либо явную тему, либо из окружающей среды? Ошибки?// MARK: - Tokens
protocol ThemeTextTokens {
var primaryColor: Color { get }
var font: Font { get }
}

protocol ThemeButtonTokens {
var neutralColor: Color { get }
var positivColor: Color { get }
var accentColor: Color { get }
}

// MARK: - Theme Protocol
protocol ThemeProtocol {
associatedtype TextTokens: ThemeTextTokens
associatedtype ButtonTokens: ThemeButtonTokens

var text: TextTokens { get }
var button: ButtonTokens { get }
}

// MARK: - Concrete Theme
public struct MyTheme: ThemeProtocol {
struct TextTokens: ThemeTextTokens {
var primaryColor: Color = .primary
var font: Font = .title

// Extra property not in the protocol
var accentColor: Color = .accentColor
}

struct ButtonTokens: ThemeButtonTokens {
var neutralColor: Color = .primary
var positivColor: Color = .green
var accentColor: Color = .accentColor
}

var text = TextTokens()
var button = ButtonTokens()
}

// MARK: - Environment
private struct ThemeEnvKey: EnvironmentKey {
static var defaultValue: (any ThemeProtocol)? = nil
}

extension EnvironmentValues {
var appTheme: (any ThemeProtocol)? {
get { self[ThemeEnvKey.self] }
set { self[ThemeEnvKey.self] = newValue }
}
}

// MARK: - ViewModifier
struct ThemedModifier: ViewModifier {
let theme: Theme?
@Environment(\.appTheme) private var envTheme

func body(content: Content) -> some View {
guard let theme = theme ?? (envTheme as? Theme) else {
return AnyView(content)
}

let font = theme.text.font
let textColor = theme.text.primaryColor

return AnyView(
content
.font(font)
.foregroundColor(textColor)
)
}
}

extension View {
func themed(_ theme: Theme? = nil) -> some View {
modifier(ThemedModifier(theme: theme))
}
}

// MARK: - Demo
struct ContainerView: View {
var body: some View {
ContentView()
.environment(\.appTheme, MyTheme())
}
}

struct ContentView: View {
@Environment(\.appTheme) private var theme

var body: some View {
VStack(spacing: 12) {
// direct access
Text("Hello, World!")
.foregroundColor(theme?.text.primaryColor ?? .black)

// downcast to concrete type works
Text("Hello, Accent!")
.foregroundColor((theme as? MyTheme)?.text.accentColor ?? .black)

// ❌ compile error:
// "Type 'any ThemeProtocol' cannot conform to 'ThemeProtocol'"
Text("Hello, Modifier external!")
.themed(theme)

// OK
Text("Hello, Modifier internal!")
.themed(theme)
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... nvironment
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»