你能在 Swift 中同时定义和实例化隐式类型吗?
Can you simultaneously define and instantiate implicit types in Swift?
只是想着我想如何构建一些 UserDefaults 的语言,这些 UserDefaults 可以根据层次结构自动生成键。这让我想知道...是否可以像这样同时定义和实例化一个类型?
let myUserSettings = {
let formatting = {
var lastUsedFormat:String
}
}
let lastUsedFormat = myUserSettings.formatting.lastUsedFormat
Note: I can't use statics because I specifically need instancing so nested structs/classes with static members will not work for my case.
这是我能想到的最接近的东西,但我讨厌必须创建初始值设定项来设置成员。我希望有一些不那么冗长的东西。
class DefaultsScope {
init(_ userDefaults:UserDefaults){
self.userDefaults = userDefaults
}
let userDefaults:UserDefaults
func keyForSelf(property:String = #function) -> String {
return "\(String(reflecting: self)).\(property)"
}
}
let sharedDefaults = SharedDefaults(UserDefaults(suiteName: "A")!)
class SharedDefaults : DefaultsScope {
override init(_ userDefaults:UserDefaults){
formatting = Formatting(userDefaults)
misc = Misc(userDefaults)
super.init(userDefaults)
}
let formatting:Formatting
class Formatting:DefaultsScope {
let maxLastUsedFormats = 5
fileprivate(set) var lastUsedFormats:[String]{
get { return userDefaults.stringArray(forKey:keyForSelf()) ?? [] }
set { userDefaults.set(newValue, forKey:keyForSelf()) }
}
func appendFormat(_ format:String) -> [String] {
var updatedListOfFormats = Array<String>(lastUsedFormats.suffix(maxLastUsedFormats - 1))
updatedListOfFormats.append(format)
lastUsedFormats = updatedListOfFormats
return updatedListOfFormats
}
}
let misc:Misc
class Misc:DefaultsScope {
var someBool:Bool{
get { return userDefaults.bool(forKey:keyForSelf()) }
set { userDefaults.set(newValue, forKey:keyForSelf()) }
}
}
}
那么有没有更简单的方法呢?
免责声明:这可能只是一个抽象的解决方案,不应在现实生活中使用:)
enum x {
enum y {
static func success() {
print("Success")
}
}
}
x.y.success()
更新:对不起,伙计们,我无法停止试验。这个看起来很糟糕:)
let x2= [
"y2": [
"success": {
print("Success")
}
]
]
x2["y2"]?["success"]?()
更新 2:再次尝试,这次使用元组。由于元组必须至少有两个值,所以我不得不在其中添加一些虚拟对象。此外,元组不能具有变异函数。
let x3 = (
y3: (
success: {
print("Success")
},
failure: {
print("Failure")
}
),
z3: 0
)
x3.y3.success()
你不能拥有那种结构,但你不能从 x 内部访问 y,因为 y 只在 x 的范围内可见,而 success 在 y 的范围内也是可见的。您无法从外部访问它们
另一种选择是拥有像这样的高阶函数,return 闭包是可调用的。
let x = {
{
{
print("Success")
}
}
}
let y = x()
let success = y()
success()
或
x()()()
userdefaults 的高阶函数在现实世界中的用法可能是这样的,
typealias StringType = (String) -> ((String) -> Void)
typealias IntType = (String) -> ((Int) -> Void)
typealias BoolType = (String) -> ((Bool) -> Void)
typealias StringValue = (String) -> String?
typealias IntValue = (String) -> Int?
typealias BoolValue = (String) -> Bool?
func userDefaults<T>(_ defaults: UserDefaults) -> (String) -> ((T) -> Void) {
return { key in
return { value in
defaults.setValue(value, forKey: key)
}
}
}
func getDefaultsValue<T>(_ defaults: UserDefaults) -> (String) -> T? {
return { key in
return defaults.value(forKey: key) as? T
}
}
let setStringDefaults: StringType = userDefaults(.standard)
setStringDefaults("Name")("Jack Jones")
setStringDefaults("Address")("Australia")
let setIntDefaults: IntType = userDefaults(.standard)
setIntDefaults("Age")(35)
setIntDefaults("Salary")(2000)
let setBoolDefaults: BoolType = userDefaults(.standard)
setBoolDefaults("Married")(false)
setBoolDefaults("Employed")(true)
let getStringValue: StringValue = getDefaultsValue(.standard)
let name = getStringValue("Name")
let address = getStringValue("Address")
let getIntValue: IntValue = getDefaultsValue(.standard)
let age = getIntValue("Age")
let salary = getIntValue("Salary")
let getBoolValue: BoolValue = getDefaultsValue(.standard)
let married = getBoolValue("Married")
let employed = getBoolValue("Employed")
我不确定你是否喜欢这个模式,但它有一些很好的用例,你可以从下面看到,setStringDefaults 你可以将字符串值设置为字符串键,而且它们都是类型安全的。
您可以针对您的用例扩展它。但是,您也可以使用 struct 并使用命令式代码,这样更容易理解。我也看到了美。
你试试嵌套一些 swift structs
怎么样?
struct x {
struct y {
static func success() {
print("success")
}
}
}
x.y.success()
好的,我想我已经明白了。第一个 class 可以放入您用于所有应用程序的一些公共库中。
class SettingsScopeBase {
private init(){}
static func getKey(setting:String = #function) -> String {
return "\(String(reflecting:self)).\(setting)"
}
}
下一部分是一对classes:
- 'Scoping' class 定义要使用的用户默认实例(以及您可能希望为此特定设置实例指定的任何其他内容)
- 定义您的设置的实际层次结构
这是第一个。我正在为我的应用程序及其扩展之间的共享设置进行设置:
class SharedSettingsScope : SettingsScopeBase{
static let defaults = UserDefaults(suiteName: "group.com.myco.myappgroup")!
}
最后,这里是您如何 'set up' 您的层次结构以及如何实现属性的主体。
class SharedSettings:SharedSettingsScope{
class Formatting:SharedSettingsScope{
static var groupsOnWhitespaceOnlyLines:Bool{
get { return defaults.bool(forKey: getKey()) }
set { defaults.set(newValue, forKey: getKey()) }
}
}
}
下面是您如何使用它们...
let x = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines
// x = false
SharedSettings.Formatting.groupsOnWhitespaceOnlyLines = true
let y = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines
// y = true
我会看看我是否可以 refine/optimize 再多一点,但这离我想去的地方很近。没有 hard-coded 字符串,由使用它们的层次结构定义的键,并且只在一个地方设置特定的 UserDefaults 实例。
只是想着我想如何构建一些 UserDefaults 的语言,这些 UserDefaults 可以根据层次结构自动生成键。这让我想知道...是否可以像这样同时定义和实例化一个类型?
let myUserSettings = {
let formatting = {
var lastUsedFormat:String
}
}
let lastUsedFormat = myUserSettings.formatting.lastUsedFormat
Note: I can't use statics because I specifically need instancing so nested structs/classes with static members will not work for my case.
这是我能想到的最接近的东西,但我讨厌必须创建初始值设定项来设置成员。我希望有一些不那么冗长的东西。
class DefaultsScope {
init(_ userDefaults:UserDefaults){
self.userDefaults = userDefaults
}
let userDefaults:UserDefaults
func keyForSelf(property:String = #function) -> String {
return "\(String(reflecting: self)).\(property)"
}
}
let sharedDefaults = SharedDefaults(UserDefaults(suiteName: "A")!)
class SharedDefaults : DefaultsScope {
override init(_ userDefaults:UserDefaults){
formatting = Formatting(userDefaults)
misc = Misc(userDefaults)
super.init(userDefaults)
}
let formatting:Formatting
class Formatting:DefaultsScope {
let maxLastUsedFormats = 5
fileprivate(set) var lastUsedFormats:[String]{
get { return userDefaults.stringArray(forKey:keyForSelf()) ?? [] }
set { userDefaults.set(newValue, forKey:keyForSelf()) }
}
func appendFormat(_ format:String) -> [String] {
var updatedListOfFormats = Array<String>(lastUsedFormats.suffix(maxLastUsedFormats - 1))
updatedListOfFormats.append(format)
lastUsedFormats = updatedListOfFormats
return updatedListOfFormats
}
}
let misc:Misc
class Misc:DefaultsScope {
var someBool:Bool{
get { return userDefaults.bool(forKey:keyForSelf()) }
set { userDefaults.set(newValue, forKey:keyForSelf()) }
}
}
}
那么有没有更简单的方法呢?
免责声明:这可能只是一个抽象的解决方案,不应在现实生活中使用:)
enum x {
enum y {
static func success() {
print("Success")
}
}
}
x.y.success()
更新:对不起,伙计们,我无法停止试验。这个看起来很糟糕:)
let x2= [
"y2": [
"success": {
print("Success")
}
]
]
x2["y2"]?["success"]?()
更新 2:再次尝试,这次使用元组。由于元组必须至少有两个值,所以我不得不在其中添加一些虚拟对象。此外,元组不能具有变异函数。
let x3 = (
y3: (
success: {
print("Success")
},
failure: {
print("Failure")
}
),
z3: 0
)
x3.y3.success()
你不能拥有那种结构,但你不能从 x 内部访问 y,因为 y 只在 x 的范围内可见,而 success 在 y 的范围内也是可见的。您无法从外部访问它们
另一种选择是拥有像这样的高阶函数,return 闭包是可调用的。
let x = {
{
{
print("Success")
}
}
}
let y = x()
let success = y()
success()
或
x()()()
userdefaults 的高阶函数在现实世界中的用法可能是这样的,
typealias StringType = (String) -> ((String) -> Void)
typealias IntType = (String) -> ((Int) -> Void)
typealias BoolType = (String) -> ((Bool) -> Void)
typealias StringValue = (String) -> String?
typealias IntValue = (String) -> Int?
typealias BoolValue = (String) -> Bool?
func userDefaults<T>(_ defaults: UserDefaults) -> (String) -> ((T) -> Void) {
return { key in
return { value in
defaults.setValue(value, forKey: key)
}
}
}
func getDefaultsValue<T>(_ defaults: UserDefaults) -> (String) -> T? {
return { key in
return defaults.value(forKey: key) as? T
}
}
let setStringDefaults: StringType = userDefaults(.standard)
setStringDefaults("Name")("Jack Jones")
setStringDefaults("Address")("Australia")
let setIntDefaults: IntType = userDefaults(.standard)
setIntDefaults("Age")(35)
setIntDefaults("Salary")(2000)
let setBoolDefaults: BoolType = userDefaults(.standard)
setBoolDefaults("Married")(false)
setBoolDefaults("Employed")(true)
let getStringValue: StringValue = getDefaultsValue(.standard)
let name = getStringValue("Name")
let address = getStringValue("Address")
let getIntValue: IntValue = getDefaultsValue(.standard)
let age = getIntValue("Age")
let salary = getIntValue("Salary")
let getBoolValue: BoolValue = getDefaultsValue(.standard)
let married = getBoolValue("Married")
let employed = getBoolValue("Employed")
我不确定你是否喜欢这个模式,但它有一些很好的用例,你可以从下面看到,setStringDefaults 你可以将字符串值设置为字符串键,而且它们都是类型安全的。
您可以针对您的用例扩展它。但是,您也可以使用 struct 并使用命令式代码,这样更容易理解。我也看到了美。
你试试嵌套一些 swift structs
怎么样?
struct x {
struct y {
static func success() {
print("success")
}
}
}
x.y.success()
好的,我想我已经明白了。第一个 class 可以放入您用于所有应用程序的一些公共库中。
class SettingsScopeBase {
private init(){}
static func getKey(setting:String = #function) -> String {
return "\(String(reflecting:self)).\(setting)"
}
}
下一部分是一对classes:
- 'Scoping' class 定义要使用的用户默认实例(以及您可能希望为此特定设置实例指定的任何其他内容)
- 定义您的设置的实际层次结构
这是第一个。我正在为我的应用程序及其扩展之间的共享设置进行设置:
class SharedSettingsScope : SettingsScopeBase{
static let defaults = UserDefaults(suiteName: "group.com.myco.myappgroup")!
}
最后,这里是您如何 'set up' 您的层次结构以及如何实现属性的主体。
class SharedSettings:SharedSettingsScope{
class Formatting:SharedSettingsScope{
static var groupsOnWhitespaceOnlyLines:Bool{
get { return defaults.bool(forKey: getKey()) }
set { defaults.set(newValue, forKey: getKey()) }
}
}
}
下面是您如何使用它们...
let x = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines
// x = false
SharedSettings.Formatting.groupsOnWhitespaceOnlyLines = true
let y = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines
// y = true
我会看看我是否可以 refine/optimize 再多一点,但这离我想去的地方很近。没有 hard-coded 字符串,由使用它们的层次结构定义的键,并且只在一个地方设置特定的 UserDefaults 实例。