在使用协议强制转换访问计算变量期间,Setter调用了struct

时间:2015-10-05 21:57:11

标签: swift struct protocols swift2 setter

我为遵循协议的结构创建了一个全局变量。该变量有一个setter观察者,只要设置了变量就可以完成任务。由于结构本身遵循协议,我希望变量的类型是协议类型。

hPipe = CreateFile(L"\\\\10.0.0.11\\Pipe\\", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
DWORD dwErr = GetLastError();  // returns 123
if(hPipe == INVALID_HANDLE_VALUE)
    return 1;

问题在于,当我获得在struct中作为计算属性的协议属性的值时,也会调用变量setter。

protocol TestProtocol {
    var someInt: Int {get set}
    var computedVar: Int {get}
    func funcCall() -> Int
}

struct TestStruct: TestProtocol {
    var someInt: Int = 1

    var computedVar: Int {
        return 0
    } 

    func funcCall() -> Int {
        return 2
    }
}

var testProtocolVar: TestProtocol = TestStruct() {
    willSet(newTest) {
        print ("*** Setter testProtocolVar called!!!")
    }
}

类似的情况,变量属于结构类型,不会触发设置器。

/***
  When a variable is defined and typecast as a protocol, calling a
  computed variable on the variable (a class or a struct) the setter 
  method of the variable will be called (Undesired Behaviour).
***/

print ("\n\n *** Test Protocol Cast Variable *** \n\n")
testProtocolVar
testProtocolVar.someInt
print("Setter has not been called")
testProtocolVar.funcCall()
print("Setter has not been called after function")
testProtocolVar.computedVar
print("Setter has been called when using computed variable")

/*
    *** Test Protocol Cast Variable *** 


   Setter has not been called
   Setter has not been called after function
   *** Setter testProtocolVar called!!!
   Setter has been called when using computed variable
*/

有没有人解释为什么要调用setter观察者?

除非我遗漏了某些内容,否则这似乎是swift中的一个错误。

2 个答案:

答案 0 :(得分:2)

这似乎已在Xcode 7.2 beta 2中正式修复

  

Xcode 7.2 beta 2中解决的问题 - Swift 2.1和Objective-C Swift   编译器在Swift的早期版本中,如果类型具有可变性   协议类型的属性,"链接"访问该属性   财产总是被视为财产的突变,即使是   第二个属性只读,不写。例如:

  protocol Countable {
       var count: Int { get }
  }
  class MyObject {
      var widgets : Countable {
             didSet { print("in didSet") }
} }
  var obj : MyObject = ...
  let count = obj.widgets.count
     

这将执行虚假写回属性小部件,   导致didSet意外触发。解决方法是拆分   访问单独的表达式,如:

  let widgets = obj.widgets
  let count = widgets.count
     

此错误现已修复。 (22953072)

答案 1 :(得分:0)

cluster.SCHED_NONE
你认为这是一个错误吗?对我来说似乎很好......

  

willSet和didSet观察者提供了一种观察(和   当变量或属性的值为时,适当地响应)   被设定。变量或属性时不调用观察者   首先被初始化。相反,它们仅在值为时被调用   在初始化上下文之外设置。