@使用Swift Combine作为函数参数发布

问题描述

我希望能够将对@Published属性的引用作为参数传递给其他对象,以便其他对象可以使用,编辑和查看该属性上的数据,并且我希望在保留Property功能的同时做到这一点Swift中的包装器

这是我的例子。我创建一个MainStore对象。它具有@Published名称数组。我可以在整个应用程序中使用该对象,也可以在names中更改数据,任何订阅的地方都会得到更新。

class MainStore {
    @Published var names: [String]
    
    init(names: [String]) {
        self.names = names
    }
}

现在我要创建第二个商店。它具有一些附加功能,需要更加集中,但是我希望它引用MainStore中的names属性。当MainStore.names被更新时,我也希望SecondStore.names也被更新。当SecondStore.names更新时,我也希望MainStore.names也更新。

class SecondStore {
    
    @Published var names: [String]
    
    init(@Published names: [String]) {
        self.names = names
    }
}

我也希望使用@Published属性包装的语法

例如SecondStore.names.append("Billy")SecondStore.$names.sink() { }

有没有办法做到这一点,如果不是,建议的做法是完成我的一般指导?

解决方法

您可以将import Data.Either (either) import Text.Printf (printf) data Record = Record { fieldA :: String,fieldB :: String,fieldC :: String } deriving (Show,Eq) type Err = String setField :: String -> String -> Either Err String setField field value | length value > 0 = Right value | otherwise = Left $ printf "value for field %s is to short" field setFieldA :: String -> Either Err String setFieldA = setField "fieldA" setFieldB :: String -> Either Err String setFieldB = setField "fieldB" setFieldC :: String -> Either Err String setFieldC = setField "fieldC" makeRecord :: Either Err Record makeRecord = Record <$> setField "fieldA" "valueA" <*> setField "fieldB" "valueB" <*> setField "fieldC" "valueC" makeRecord' :: Either Err Record makeRecord' = Record <$> setFieldA "valueA" <*> setFieldB "valueB" <*> setFieldC "valueC" recordFromEither :: Either Err Record -> Maybe Record recordFromEither r = case r of Right v -> Just $ v Left _ -> Nothing main :: IO () main = putStrLn $ output where output = case makeRecord of Right v -> show v Left err -> show err main' :: IO () main' = putStrLn $ either id show makeRecord' 对象传递到MainStore,然后收听到对SecondStore属性所做的更改。

mainStore.names
class MainStore {
    @Published var names: [String]

    init(names: [String]) {
        self.names = names
    }
}

请注意,在class SecondStore { @Published var names: [String] = [] private var cancellables = Set<AnyCancellable>() init(mainStore: MainStore) { // listen to the `$names` publisher mainStore.$names // all `@Published` properties must be updated on the `main` thread .receive(on: RunLoop.main) // assign received value to self.names .sink { [weak self] in self?.names = $0 } // keep it in memory so it won't be cancelled .store(in: &cancellables) } } 部分中,可能存在较强的参考周期。

这就是为什么使用.sink的原因。您可以在此处了解更多信息:Weak Self in Swift Made Easy: What it is and why it’s needed

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...