读一次然后设置为零

时间:2017-07-07 15:52:56

标签: swift properties

我想要实现这样的属性,它的值只能读取一次,然后属性应该设置为nil

我已经以这种方式实施了它:

private var _readOnce: String?

var readOnce: String? {
    get {
        let value = _readOnce
        _readOnce = nil
        return value
        }
    set {
        _readOnce = newValue
    }
}

readOnce = "Andrej"

print("read once = \(readOnce)")  // prints read once = Optional("Andrej")\n"
print("read once = \(readOnce)")  // prints read once = nil\n"

但我觉得使用单独的属性_readOnce不是" swifty" /"最优雅的#34;这样做的方法。

有没有人知道不同的方式,不需要使用单独的财产?

我可以确认上面的代码是有效的,只是我认为它可以更优雅,更少的线条来实现相同的行为。

2 个答案:

答案 0 :(得分:2)

我不知道有办法避免拥有支持属性,但我可能做的就是制作一个帮助类型来包装行为。像这样:

public class NameOne {

public static void main(String[] args) {
    File FolderA = new File("C:/Users/hoflerj/Desktop/FolderA");
    File [] filesOne = FolderA.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File FolderA, String nameOne) {
            //return name.endsWith(".txt");
            return nameOne.contains("test");
        }
    });


    for (File txtfile : filesOne) {
       if ( txtfile.getName().contains("t")){
            System.out.println("Match found ---> " + (txtfile));
            //System.out.println(txtfile);
       }
            else{

                System.out.println("(FolderA) not contain specified match");

            }
        }

    System.out.println("\n");

    File FolderB = new File("C:/Users/hoflerj/Desktop/FolderB");
    File [] filesTwo = FolderB.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File FolderB, String nameTwo) {
            //return name.endsWith(".txt");
            return nameTwo.contains("test");
        }
    });

    for (File txtfile : filesTwo) {
           if ( txtfile.getName().contains("t")){
                System.out.println("Match found ---> " + (txtfile));
           }
                else{
                    System.out.println("(FolderB) not contain specified match");

                }
            }



    }   

}

如果您愿意,也可以通过struct OneTimeValue<T> { private var isUnread = true private let value : T init(_ value: T) { self.value = value } func get() -> T? { guard isUnread else { return nil } self.isUnread = false return self.value } } nil value内部get()编写此内容,但总体规划仍然有效。

然后你的班级成为:

class Miser
{
    var readOnce : String?
    {
        return self._readOnce.get()
    }
    private let _readOnce = OneTimeValue("Can't touch this (twice)")
}

我还将此模式用于UserDefaultsValue(存储到/来自用户默认值)和SynchronizedValue(属性上的读写锁定),我认为它运行良好。

答案 1 :(得分:1)

据我所知,没有第二个变量是不可能的。这是因为计算属性不存储它们所代表的变量的任何数据:

  

除了存储的属性,类,结构和   枚举可以定义计算属性,但实际上并不是这样   存储一个值。

对于非计算属性,您可以拥有的唯一观察者是基于变量的设置,而不是获取(即willSetdidSet

希望有所帮助!

编辑: 如果你小心的话,它可以用闭包和属性观察者完成: 这不需要其他变量(而是由闭包捕获值),但是相当不清楚 - 我不推荐它。

var readOnce: () -> String? = {nil} {
    didSet{
        readOnce = { [weak self, readOnce] in
            self?.readOnce = {nil}
            return readOnce()
        }
    }
}

readOnce()        // returns nil
readOnce = {"Hi"} 
readOnce()        // returns optional wrapped "Hi"
readOnce()        // returns nil

为您提供更“快捷”的答案:D