Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift中将函数分配给块时捕获语义?_Ios_Swift_Memory Management_Automatic Ref Counting_Retain Cycle - Fatal编程技术网

Ios 在Swift中将函数分配给块时捕获语义?

Ios 在Swift中将函数分配给块时捕获语义?,ios,swift,memory-management,automatic-ref-counting,retain-cycle,Ios,Swift,Memory Management,Automatic Ref Counting,Retain Cycle,我想知道在Swift中为一个块分配一个函数在内存管理方面意味着什么(即,我想避免一个保留周期) 例如,假设我有一个具有以下定义的按钮: class Button { var wasTapped: () -> Void } 我在视图控制器中使用它,如下所示: class ViewController { let button: Button func setUpButtonHandler() { button.wasTapped = ... } func b

我想知道在Swift中为一个块分配一个函数在内存管理方面意味着什么(即,我想避免一个保留周期)

例如,假设我有一个具有以下定义的按钮:

class Button {
  var wasTapped: () -> Void
}
我在视图控制器中使用它,如下所示:

class ViewController {
  let button: Button

  func setUpButtonHandler() {
    button.wasTapped = ...
  }

  func buttonWasTapped() {
    // do something
  }
}
我的问题是关于
button.wasTapped=…
的分配

显然,如果我这样设置:

button.wasTapped = { self.buttonWasTapped() }
我刚刚创建了一个保留循环:ViewController->Button->ViewController

但是,Swift允许我这样做:

button.wasTapped = buttonWasTapped

这样做安全吗?(即,这是否会阻止保留周期?

仍然会创建保留周期

思考这个问题的一个好方法是认识到,无论何时,只要你看到:

button.wasTapped = buttonWasTapped
这只是以下的简写:

button.wasTapped = { self.buttonWasTapped() }
这显然创造了一个保留周期,正如
self
的明确使用所表明的那样

这令人困惑,因为保留周期在第二个版本中很明显,但在第一个版本中却不明显。

不幸的是,这意味着您需要坚持更详细的内容(并保留循环):


您可以通过以下方式验证此行为:

class Button {
  var wasTapped: () -> Void

  init() {
    wasTapped = {}
  }
}

class ViewController {
  let button: Button

  func setUpButtonHandler() {
    //button.wasTapped = { [weak self] in self?.buttonWasTapped() } // no retain cycle
    //button.wasTapped = { self.buttonWasTapped() } // retain cycle
    //button.wasTapped = buttonWasTapped // retain cycle
  }

  func buttonWasTapped() {
    print("tapped!")
  }

  init() {
    button = Button()
    setUpButtonHandler()
  }

  deinit {
    print("deinit")
  }
}

func test() {
  let vc = ViewController()
  vc.button.wasTapped()
}

test()


更新:更多详细信息可在此处找到:

这仍然会创建保留周期

思考这个问题的一个好方法是认识到,无论何时,只要你看到:

button.wasTapped = buttonWasTapped
这只是以下的简写:

button.wasTapped = { self.buttonWasTapped() }
这显然创造了一个保留周期,正如
self
的明确使用所表明的那样

这令人困惑,因为保留周期在第二个版本中很明显,但在第一个版本中却不明显。

不幸的是,这意味着您需要坚持更详细的内容(并保留循环):


您可以通过以下方式验证此行为:

class Button {
  var wasTapped: () -> Void

  init() {
    wasTapped = {}
  }
}

class ViewController {
  let button: Button

  func setUpButtonHandler() {
    //button.wasTapped = { [weak self] in self?.buttonWasTapped() } // no retain cycle
    //button.wasTapped = { self.buttonWasTapped() } // retain cycle
    //button.wasTapped = buttonWasTapped // retain cycle
  }

  func buttonWasTapped() {
    print("tapped!")
  }

  init() {
    button = Button()
    setUpButtonHandler()
  }

  deinit {
    print("deinit")
  }
}

func test() {
  let vc = ViewController()
  vc.button.wasTapped()
}

test()

更新:更多详细信息可在此处找到:

帮助帖:)+1帮助帖:)+1