Swift 带有外部检测的Mutating func要变异的变量

Swift 带有外部检测的Mutating func要变异的变量,swift,mutating-function,Swift,Mutating Function,我有一个有两个变量的结构。这个结构有一个变异函数,但在这个函数中我需要检查要变异的变量。为此,我使用带有复杂逻辑的独立类静态函数。这个类使用不同的结构,所以出于简单的目的,我不能在所有这些结构中表示这个逻辑 问题是,我不知道如何从这个单独的类接收相同的结构变量,因此没有结构变量发生变化。我想,我错过了一些快速的知识,因为我确信,这是可能的,没有重复的逻辑 在操场上表示它的代码: struct SomeStruct { var a = "a" var b = "b" mu

我有一个有两个变量的结构。这个结构有一个变异函数,但在这个函数中我需要检查要变异的变量。为此,我使用带有复杂逻辑的独立类静态函数。这个类使用不同的结构,所以出于简单的目的,我不能在所有这些结构中表示这个逻辑

问题是,我不知道如何从这个单独的类接收相同的结构变量,因此没有结构变量发生变化。我想,我错过了一些快速的知识,因为我确信,这是可能的,没有重复的逻辑

在操场上表示它的代码:

struct SomeStruct {
    var a = "a"
    var b = "b"

    mutating func mutateString(to newString: String) {
        var varToMutate = VariableDetector.whichVarToMutate(a, b)
        varToMutate = newString

        // prints to represent question
        print("varToMutate: \(varToMutate)")
        print("a: \(a)")
        print("b: \(b)")
    }
}

class VariableDetector {
    static func whichVarToMutate(_ first: String, _ second: String) -> String {
        var firstOrSecondString = ""

        // simple logic to represent question, in real case it is far more complex
        if first == "a" {
            firstOrSecondString = first
        } else {
            firstOrSecondString = second
        }

        return firstOrSecondString
    }
}

var someStruct = SomeStruct()
someStruct.mutateString(to: "c")
此代码生成:

varToMutate: c
a: a
b: b
是的,可以通过以下方式解决:

if varToMutate == a {
    a = newString
} else if varToMutate == b {
    b = newString
}
但我想用更优雅的方式来解决:)


谢谢你的帮助

除非
a
b
是类的实例,否则您的
varToMutate
将只是一个副本,因为类之外的所有内容都是Swift中的值类型。也许可以尝试
unsafemeutablepointer

除非
a
b
是类的实例,否则您的
varToMutate
将只是一个副本,因为在Swift中,除了类之外的所有内容都是值类型。也许可以在Swift 4中尝试
unsafemeutablepointer

,这可以通过从
返回一个
键路径来完成,该键路径为vartomutate
。然后可以使用
KeyPath
访问相关实例,并修改它所表示的属性

在Swift 3中,我可以想到两种方法:

  • 将一个mutator闭包传递给decider方法,decider方法传递适当的var以作为
    inout
    param进行变异,然后让闭包体对其进行变异
  • 定义一个包含这些变量的协议(您所说的在多个类型之间共享),使这些类型符合它,并在协议上提供一个扩展,该扩展定义了一个方法,该方法将应用于所有类型。这是我将使用的方法,即使在Swift 4中:

    struct SomeStruct {
        var a = "a"
        var b = "b"
    }
    
    protocol Mutable { // TODO: Rename me appropriately
        var a: String { get set }
        var b: String { get set }
    }
    
    extension SomeStruct: Mutable {}
    
    extension Mutable {
        mutating func changeAppropriateVar(to newValue: String) -> Void {
            // simple logic to represent question, in real case it is far more complex
            let someCondition = true
    
            if someCondition {
                print("Setting `a` to \(newValue)")
                a = newValue
            }
            else {
                print("Setting `b` to \(newValue)")
                b = newValue
            }
        }
    }
    
    var s = SomeStruct()
    s.changeAppropriateVar(to: "foo")
    

  • 在Swift 4中,这可以通过从
    返回一个
    键路径来完成,该键路径为vartomutate
    。然后可以使用
    KeyPath
    访问相关实例,并修改它所表示的属性

    在Swift 3中,我可以想到两种方法:

  • 将一个mutator闭包传递给decider方法,decider方法传递适当的var以作为
    inout
    param进行变异,然后让闭包体对其进行变异
  • 定义一个包含这些变量的协议(您所说的在多个类型之间共享),使这些类型符合它,并在协议上提供一个扩展,该扩展定义了一个方法,该方法将应用于所有类型。这是我将使用的方法,即使在Swift 4中:

    struct SomeStruct {
        var a = "a"
        var b = "b"
    }
    
    protocol Mutable { // TODO: Rename me appropriately
        var a: String { get set }
        var b: String { get set }
    }
    
    extension SomeStruct: Mutable {}
    
    extension Mutable {
        mutating func changeAppropriateVar(to newValue: String) -> Void {
            // simple logic to represent question, in real case it is far more complex
            let someCondition = true
    
            if someCondition {
                print("Setting `a` to \(newValue)")
                a = newValue
            }
            else {
                print("Setting `b` to \(newValue)")
                b = newValue
            }
        }
    }
    
    var s = SomeStruct()
    s.changeAppropriateVar(to: "foo")
    

  • 另一方面,只使用类定义静态方法不是很常见。您可以只使用窄访问说明符(例如,
    fileprivate
    internal
    ,以限制全局命名空间填充)将这些方法生成函数,也可以在旁注中使用无大小写的
    enum
    (防止意外实例化),使用类来定义静态方法不是很常见。您可以使用狭义访问说明符(例如,
    fileprivate
    internal
    ,以限制全局命名空间填充)将这些方法生成函数,也可以使用无大小写的
    enum
    (防止意外实例化)Alexander,太棒了:)感谢您的回答和评论@PeterTretyakov每当您最终提取出这样的公共逻辑时,都会想“我可以用提供默认实现的协议和扩展来完成吗?”。大多数时候都是肯定的。生硬的方式:)事实上,我认为它可以用协议来解决,但协议的概念对我来说仍然不是很清楚。另外,如果有人发现了这个问题,请看WWDC2015关于面向协议编程的视频@PeterTretyakov Hah。好脾气。@PeterTretyakov你有Java背景吗?Alexander,太棒了:)谢谢你的回答和评论@PeterTretyakov每当您最终提取出这样的公共逻辑时,都会想“我可以用提供默认实现的协议和扩展来完成吗?”。大多数时候都是肯定的。生硬的方式:)事实上,我认为它可以用协议来解决,但协议的概念对我来说仍然不是很清楚。另外,如果有人发现了这个问题,请看WWDC2015关于面向协议编程的视频@PeterTretyakov Hah。好脾气。@PeterTretyakov你有Java背景吗?