Error[8]: Undefined offset: 5, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2. 在方法loadHappinessV1中: >如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化 >为了防止编译器错误,我指定对self的弱引用. 在方 需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2.

在方法loadHappinessV1中:

>如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化
>为了防止编译器错误,我指定对self的弱引用.

在方法loadHappinessV2中:

>我决定引入两个嵌套函数并简化 *** 作的“主体”.
>编译器不会引发有关捕获语义的错误.

为什么在方法loadHappinessV2编译器中不会引发有关捕获语义的错误?是否未捕获嵌套函数(以及变量callbackQueue)?

谢谢!

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         func completeWithFailure() {            callbackQueue.async { completion(.failure) }         }         func completeWithSuccess() {            callbackQueue.async { completion(.success) }         }        let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {                completeWithSuccess()            } else {                completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch 
class Test {    var bar: Int = 0    func functionA() -> (() -> ()) {        func nestedA() {            bar += 1        }        return nestedA    }    func closureA() -> (() -> ()) {        let nestedClosureA = { [uNowned self] () -> () in            self.bar += 1        }        return nestedClosureA    }}
{ case .success: print("Happiness V1 delivered .)") case .failure: print("Happiness V1 not available at the moment .(") }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 { switch
sil_scope 2 { loc "Test.swift":5:10 parent @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 3 { loc "Test.swift":10:5 parent 2 }// Test.functionA() -> () -> ()sil hIDden @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %4,%3,%1bb0(%0 : $Test):  deBUG_value %0 : $Test,let,name "self",argno 1,loc "Test.swift":5:10,scope 2 // ID: %1  // function_ref Test.(functionA() -> () -> ()).(nestedA #1)() -> ()  %2 = function_ref @Test.Test.(functionA () -> () -> ()).(nestedA #1) () -> () : $@convention(thin) (@owned Test) -> (),loc "Test.swift":9:16,scope 3 // user: %4  strong_retain %0 : $Test,scope 3 // ID: %3  %4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> (),scope 3 // user: %5  return %4 : $@callee_owned () -> (),loc "Test.swift":9:9,scope 3 // ID: %5}
{ case .success: print("Happiness V2 delivered .)") case .failure: print("Happiness V2 not available at the moment .(") }}
解决方法 我找到了一些解释如何使用嵌套函数捕获语义.资料来源: Nested functions and reference capturing.

考虑以下示例:

sil [transparent] [fragile] @Swift.Int.init (_builtinintegerliteral : Builtin.Int2048) -> Swift.Int : $@convention(method) (Builtin.Int2048,@thin Int.Type) -> Intsil_scope 6 { loc "Test.swift":12:10 parent @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 7 { loc "Test.swift":17:5 parent 6 }sil_scope 8 { loc "Test.swift":15:9 parent 7 }// Test.closureA() -> () -> ()sil hIDden @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %5,%4,loc "Test.swift":12:10,scope 6 // ID: %1  %2 = alloc_Box $@sil_weak Optional<Test>,loc "Test.swift":13:38,scope 8 // users: %13,%11,%9,%3  %3 = project_Box %2 : $@Box @sil_weak Optional<Test>,scope 8 // users: %10,%6  strong_retain %0 : $Test,scope 8 // ID: %4  %5 = enum $Optional<Test>,#Optional.some!enumelt.1,%0 : $Test,scope 8 // users: %7,%6  store_weak %5 to [initialization] %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %6  release_value %5 : $Optional<Test>,scope 8 // ID: %7  // function_ref Test.(closureA() -> () -> ()).(closure #1)  %8 = function_ref @Test.Test.(closureA () -> () -> ()).(closure #1) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),loc "Test.swift":13:30,scope 8 // user: %11  strong_retain %2 : $@Box @sil_weak Optional<Test>,scope 8 // ID: %9  mark_function_escape %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %10  %11 = partial_apply %8(%2) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),scope 8 // users: %14,%12  deBUG_value %11 : $@callee_owned () -> (),name "nestedClosureA",loc "Test.swift":13:13,scope 7 // ID: %12  strong_release %2 : $@Box @sil_weak Optional<Test>,loc "Test.swift":15:9,scope 7 // ID: %13  return %11 : $@callee_owned () -> (),loc "Test.swift":16:9,scope 7 // ID: %14}

编译器提醒我们保持函数closureA的所有权.但是没有说明在功能函数A中捕获自我的任何信息.

让我们看看Swift中间语言(SIL):
xcrun swiftc -emit-silgen Test.swift | xcrun swift-demangle> Test.silgen

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         // Closure used instead of nested function.         let completeWithFailure = { [weak self] in            self?.callbackQueue.async { completion(.failure) }         }         // Closure used instead of nested function.         let completeWithSuccess = { [weak self] in            self?.callbackQueue.async { completion(.success) }         }         let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               completeWithSuccess()            } else {               completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch [+++] {   case .success: print("Happiness V1 delivered .)")   case .failure: print("Happiness V1 not available at the moment .(")   }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 {   switch [+++] {   case .success: print("Happiness V2 delivered .)")   case .failure: print("Happiness V2 not available at the moment .(")   }}

行strong_retain%0:$Test,loc“Test.swift”:9:16,范围3 // ID:%3告诉我们编译器为$Test(定义为self)做强引用,此引用存在于范围3(即功能A)并且在离开范围3时未释放.

第二个函数closureA处理self的可选引用.它在代码中表示为%2 = alloc_Box $@ sil_weak可选< Test>,var,名称“self”,loc“Test.swift”:13:38,范围8 //用户:?,?,%9,% 3.

[+++]

因此,如果嵌套函数访问self中定义的某些属性,那么嵌套函数将保留对self的强引用.编译器不会通知它(Swift 3.0.1).

为了避免这种行为,我们只需要使用闭包而不是嵌套函数.然后编译器将通知自我使用情况.

原始示例可以重新表示如下:

[+++] 总结

以上是内存溢出为你收集整理的Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?全部内容,希望文章能够帮你解决Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 6, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2. 在方法loadHappinessV1中: >如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化 >为了防止编译器错误,我指定对self的弱引用. 在方 需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2.

在方法loadHappinessV1中:

>如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化
>为了防止编译器错误,我指定对self的弱引用.

在方法loadHappinessV2中:

>我决定引入两个嵌套函数并简化 *** 作的“主体”.
>编译器不会引发有关捕获语义的错误.

为什么在方法loadHappinessV2编译器中不会引发有关捕获语义的错误?是否未捕获嵌套函数(以及变量callbackQueue)?

谢谢!

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         func completeWithFailure() {            callbackQueue.async { completion(.failure) }         }         func completeWithSuccess() {            callbackQueue.async { completion(.success) }         }        let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {                completeWithSuccess()            } else {                completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch 
class Test {    var bar: Int = 0    func functionA() -> (() -> ()) {        func nestedA() {            bar += 1        }        return nestedA    }    func closureA() -> (() -> ()) {        let nestedClosureA = { [uNowned self] () -> () in            self.bar += 1        }        return nestedClosureA    }}
{ case .success: print("Happiness V1 delivered .)") case .failure: print("Happiness V1 not available at the moment .(") }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 { switch
sil_scope 2 { loc "Test.swift":5:10 parent @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 3 { loc "Test.swift":10:5 parent 2 }// Test.functionA() -> () -> ()sil hIDden @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %4,%3,%1bb0(%0 : $Test):  deBUG_value %0 : $Test,let,name "self",argno 1,loc "Test.swift":5:10,scope 2 // ID: %1  // function_ref Test.(functionA() -> () -> ()).(nestedA #1)() -> ()  %2 = function_ref @Test.Test.(functionA () -> () -> ()).(nestedA #1) () -> () : $@convention(thin) (@owned Test) -> (),loc "Test.swift":9:16,scope 3 // user: %4  strong_retain %0 : $Test,scope 3 // ID: %3  %4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> (),scope 3 // user: %5  return %4 : $@callee_owned () -> (),loc "Test.swift":9:9,scope 3 // ID: %5}
{ case .success: print("Happiness V2 delivered .)") case .failure: print("Happiness V2 not available at the moment .(") }}
解决方法 我找到了一些解释如何使用嵌套函数捕获语义.资料来源: Nested functions and reference capturing.

考虑以下示例:

sil [transparent] [fragile] @Swift.Int.init (_builtinintegerliteral : Builtin.Int2048) -> Swift.Int : $@convention(method) (Builtin.Int2048,@thin Int.Type) -> Intsil_scope 6 { loc "Test.swift":12:10 parent @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 7 { loc "Test.swift":17:5 parent 6 }sil_scope 8 { loc "Test.swift":15:9 parent 7 }// Test.closureA() -> () -> ()sil hIDden @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %5,%4,loc "Test.swift":12:10,scope 6 // ID: %1  %2 = alloc_Box $@sil_weak Optional<Test>,loc "Test.swift":13:38,scope 8 // users: %13,%11,%9,%3  %3 = project_Box %2 : $@Box @sil_weak Optional<Test>,scope 8 // users: %10,%6  strong_retain %0 : $Test,scope 8 // ID: %4  %5 = enum $Optional<Test>,#Optional.some!enumelt.1,%0 : $Test,scope 8 // users: %7,%6  store_weak %5 to [initialization] %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %6  release_value %5 : $Optional<Test>,scope 8 // ID: %7  // function_ref Test.(closureA() -> () -> ()).(closure #1)  %8 = function_ref @Test.Test.(closureA () -> () -> ()).(closure #1) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),loc "Test.swift":13:30,scope 8 // user: %11  strong_retain %2 : $@Box @sil_weak Optional<Test>,scope 8 // ID: %9  mark_function_escape %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %10  %11 = partial_apply %8(%2) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),scope 8 // users: %14,%12  deBUG_value %11 : $@callee_owned () -> (),name "nestedClosureA",loc "Test.swift":13:13,scope 7 // ID: %12  strong_release %2 : $@Box @sil_weak Optional<Test>,loc "Test.swift":15:9,scope 7 // ID: %13  return %11 : $@callee_owned () -> (),loc "Test.swift":16:9,scope 7 // ID: %14}

编译器提醒我们保持函数closureA的所有权.但是没有说明在功能函数A中捕获自我的任何信息.

让我们看看Swift中间语言(SIL):
xcrun swiftc -emit-silgen Test.swift | xcrun swift-demangle> Test.silgen

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         // Closure used instead of nested function.         let completeWithFailure = { [weak self] in            self?.callbackQueue.async { completion(.failure) }         }         // Closure used instead of nested function.         let completeWithSuccess = { [weak self] in            self?.callbackQueue.async { completion(.success) }         }         let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               completeWithSuccess()            } else {               completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch  {   case .success: print("Happiness V1 delivered .)")   case .failure: print("Happiness V1 not available at the moment .(")   }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 {   switch [+++] {   case .success: print("Happiness V2 delivered .)")   case .failure: print("Happiness V2 not available at the moment .(")   }}

行strong_retain%0:$Test,loc“Test.swift”:9:16,范围3 // ID:%3告诉我们编译器为$Test(定义为self)做强引用,此引用存在于范围3(即功能A)并且在离开范围3时未释放.

第二个函数closureA处理self的可选引用.它在代码中表示为%2 = alloc_Box $@ sil_weak可选< Test>,var,名称“self”,loc“Test.swift”:13:38,范围8 //用户:?,?,%9,% 3.

[+++]

因此,如果嵌套函数访问self中定义的某些属性,那么嵌套函数将保留对self的强引用.编译器不会通知它(Swift 3.0.1).

为了避免这种行为,我们只需要使用闭包而不是嵌套函数.然后编译器将通知自我使用情况.

原始示例可以重新表示如下:

[+++] 总结

以上是内存溢出为你收集整理的Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?全部内容,希望文章能够帮你解决Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 7, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2. 在方法loadHappinessV1中: >如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化 >为了防止编译器错误,我指定对self的弱引用. 在方 需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2.

在方法loadHappinessV1中:

>如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化
>为了防止编译器错误,我指定对self的弱引用.

在方法loadHappinessV2中:

>我决定引入两个嵌套函数并简化 *** 作的“主体”.
>编译器不会引发有关捕获语义的错误.

为什么在方法loadHappinessV2编译器中不会引发有关捕获语义的错误?是否未捕获嵌套函数(以及变量callbackQueue)?

谢谢!

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         func completeWithFailure() {            callbackQueue.async { completion(.failure) }         }         func completeWithSuccess() {            callbackQueue.async { completion(.success) }         }        let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {                completeWithSuccess()            } else {                completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch 
class Test {    var bar: Int = 0    func functionA() -> (() -> ()) {        func nestedA() {            bar += 1        }        return nestedA    }    func closureA() -> (() -> ()) {        let nestedClosureA = { [uNowned self] () -> () in            self.bar += 1        }        return nestedClosureA    }}
{ case .success: print("Happiness V1 delivered .)") case .failure: print("Happiness V1 not available at the moment .(") }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 { switch
sil_scope 2 { loc "Test.swift":5:10 parent @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 3 { loc "Test.swift":10:5 parent 2 }// Test.functionA() -> () -> ()sil hIDden @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %4,%3,%1bb0(%0 : $Test):  deBUG_value %0 : $Test,let,name "self",argno 1,loc "Test.swift":5:10,scope 2 // ID: %1  // function_ref Test.(functionA() -> () -> ()).(nestedA #1)() -> ()  %2 = function_ref @Test.Test.(functionA () -> () -> ()).(nestedA #1) () -> () : $@convention(thin) (@owned Test) -> (),loc "Test.swift":9:16,scope 3 // user: %4  strong_retain %0 : $Test,scope 3 // ID: %3  %4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> (),scope 3 // user: %5  return %4 : $@callee_owned () -> (),loc "Test.swift":9:9,scope 3 // ID: %5}
{ case .success: print("Happiness V2 delivered .)") case .failure: print("Happiness V2 not available at the moment .(") }}
解决方法 我找到了一些解释如何使用嵌套函数捕获语义.资料来源: Nested functions and reference capturing.

考虑以下示例:

sil [transparent] [fragile] @Swift.Int.init (_builtinintegerliteral : Builtin.Int2048) -> Swift.Int : $@convention(method) (Builtin.Int2048,@thin Int.Type) -> Intsil_scope 6 { loc "Test.swift":12:10 parent @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 7 { loc "Test.swift":17:5 parent 6 }sil_scope 8 { loc "Test.swift":15:9 parent 7 }// Test.closureA() -> () -> ()sil hIDden @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %5,%4,loc "Test.swift":12:10,scope 6 // ID: %1  %2 = alloc_Box $@sil_weak Optional<Test>,loc "Test.swift":13:38,scope 8 // users: %13,%11,%9,%3  %3 = project_Box %2 : $@Box @sil_weak Optional<Test>,scope 8 // users: %10,%6  strong_retain %0 : $Test,scope 8 // ID: %4  %5 = enum $Optional<Test>,#Optional.some!enumelt.1,%0 : $Test,scope 8 // users: %7,%6  store_weak %5 to [initialization] %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %6  release_value %5 : $Optional<Test>,scope 8 // ID: %7  // function_ref Test.(closureA() -> () -> ()).(closure #1)  %8 = function_ref @Test.Test.(closureA () -> () -> ()).(closure #1) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),loc "Test.swift":13:30,scope 8 // user: %11  strong_retain %2 : $@Box @sil_weak Optional<Test>,scope 8 // ID: %9  mark_function_escape %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %10  %11 = partial_apply %8(%2) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),scope 8 // users: %14,%12  deBUG_value %11 : $@callee_owned () -> (),name "nestedClosureA",loc "Test.swift":13:13,scope 7 // ID: %12  strong_release %2 : $@Box @sil_weak Optional<Test>,loc "Test.swift":15:9,scope 7 // ID: %13  return %11 : $@callee_owned () -> (),loc "Test.swift":16:9,scope 7 // ID: %14}

编译器提醒我们保持函数closureA的所有权.但是没有说明在功能函数A中捕获自我的任何信息.

让我们看看Swift中间语言(SIL):
xcrun swiftc -emit-silgen Test.swift | xcrun swift-demangle> Test.silgen

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         // Closure used instead of nested function.         let completeWithFailure = { [weak self] in            self?.callbackQueue.async { completion(.failure) }         }         // Closure used instead of nested function.         let completeWithSuccess = { [weak self] in            self?.callbackQueue.async { completion(.success) }         }         let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               completeWithSuccess()            } else {               completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch  {   case .success: print("Happiness V1 delivered .)")   case .failure: print("Happiness V1 not available at the moment .(")   }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 {   switch  {   case .success: print("Happiness V2 delivered .)")   case .failure: print("Happiness V2 not available at the moment .(")   }}

行strong_retain%0:$Test,loc“Test.swift”:9:16,范围3 // ID:%3告诉我们编译器为$Test(定义为self)做强引用,此引用存在于范围3(即功能A)并且在离开范围3时未释放.

第二个函数closureA处理self的可选引用.它在代码中表示为%2 = alloc_Box $@ sil_weak可选< Test>,var,名称“self”,loc“Test.swift”:13:38,范围8 //用户:?,?,%9,% 3.

[+++]

因此,如果嵌套函数访问self中定义的某些属性,那么嵌套函数将保留对self的强引用.编译器不会通知它(Swift 3.0.1).

为了避免这种行为,我们只需要使用闭包而不是嵌套函数.然后编译器将通知自我使用情况.

原始示例可以重新表示如下:

[+++] 总结

以上是内存溢出为你收集整理的Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?全部内容,希望文章能够帮你解决Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 8, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2. 在方法loadHappinessV1中: >如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化 >为了防止编译器错误,我指定对self的弱引用. 在方 需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2.

在方法loadHappinessV1中:

>如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化
>为了防止编译器错误,我指定对self的弱引用.

在方法loadHappinessV2中:

>我决定引入两个嵌套函数并简化 *** 作的“主体”.
>编译器不会引发有关捕获语义的错误.

为什么在方法loadHappinessV2编译器中不会引发有关捕获语义的错误?是否未捕获嵌套函数(以及变量callbackQueue)?

谢谢!

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         func completeWithFailure() {            callbackQueue.async { completion(.failure) }         }         func completeWithSuccess() {            callbackQueue.async { completion(.success) }         }        let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {                completeWithSuccess()            } else {                completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch 
class Test {    var bar: Int = 0    func functionA() -> (() -> ()) {        func nestedA() {            bar += 1        }        return nestedA    }    func closureA() -> (() -> ()) {        let nestedClosureA = { [uNowned self] () -> () in            self.bar += 1        }        return nestedClosureA    }}
{ case .success: print("Happiness V1 delivered .)") case .failure: print("Happiness V1 not available at the moment .(") }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 { switch
sil_scope 2 { loc "Test.swift":5:10 parent @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 3 { loc "Test.swift":10:5 parent 2 }// Test.functionA() -> () -> ()sil hIDden @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %4,%3,%1bb0(%0 : $Test):  deBUG_value %0 : $Test,let,name "self",argno 1,loc "Test.swift":5:10,scope 2 // ID: %1  // function_ref Test.(functionA() -> () -> ()).(nestedA #1)() -> ()  %2 = function_ref @Test.Test.(functionA () -> () -> ()).(nestedA #1) () -> () : $@convention(thin) (@owned Test) -> (),loc "Test.swift":9:16,scope 3 // user: %4  strong_retain %0 : $Test,scope 3 // ID: %3  %4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> (),scope 3 // user: %5  return %4 : $@callee_owned () -> (),loc "Test.swift":9:9,scope 3 // ID: %5}
{ case .success: print("Happiness V2 delivered .)") case .failure: print("Happiness V2 not available at the moment .(") }}
解决方法 我找到了一些解释如何使用嵌套函数捕获语义.资料来源: Nested functions and reference capturing.

考虑以下示例:

sil [transparent] [fragile] @Swift.Int.init (_builtinintegerliteral : Builtin.Int2048) -> Swift.Int : $@convention(method) (Builtin.Int2048,@thin Int.Type) -> Intsil_scope 6 { loc "Test.swift":12:10 parent @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 7 { loc "Test.swift":17:5 parent 6 }sil_scope 8 { loc "Test.swift":15:9 parent 7 }// Test.closureA() -> () -> ()sil hIDden @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %5,%4,loc "Test.swift":12:10,scope 6 // ID: %1  %2 = alloc_Box $@sil_weak Optional<Test>,loc "Test.swift":13:38,scope 8 // users: %13,%11,%9,%3  %3 = project_Box %2 : $@Box @sil_weak Optional<Test>,scope 8 // users: %10,%6  strong_retain %0 : $Test,scope 8 // ID: %4  %5 = enum $Optional<Test>,#Optional.some!enumelt.1,%0 : $Test,scope 8 // users: %7,%6  store_weak %5 to [initialization] %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %6  release_value %5 : $Optional<Test>,scope 8 // ID: %7  // function_ref Test.(closureA() -> () -> ()).(closure #1)  %8 = function_ref @Test.Test.(closureA () -> () -> ()).(closure #1) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),loc "Test.swift":13:30,scope 8 // user: %11  strong_retain %2 : $@Box @sil_weak Optional<Test>,scope 8 // ID: %9  mark_function_escape %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %10  %11 = partial_apply %8(%2) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),scope 8 // users: %14,%12  deBUG_value %11 : $@callee_owned () -> (),name "nestedClosureA",loc "Test.swift":13:13,scope 7 // ID: %12  strong_release %2 : $@Box @sil_weak Optional<Test>,loc "Test.swift":15:9,scope 7 // ID: %13  return %11 : $@callee_owned () -> (),loc "Test.swift":16:9,scope 7 // ID: %14}

编译器提醒我们保持函数closureA的所有权.但是没有说明在功能函数A中捕获自我的任何信息.

让我们看看Swift中间语言(SIL):
xcrun swiftc -emit-silgen Test.swift | xcrun swift-demangle> Test.silgen

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         // Closure used instead of nested function.         let completeWithFailure = { [weak self] in            self?.callbackQueue.async { completion(.failure) }         }         // Closure used instead of nested function.         let completeWithSuccess = { [weak self] in            self?.callbackQueue.async { completion(.success) }         }         let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               completeWithSuccess()            } else {               completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch  {   case .success: print("Happiness V1 delivered .)")   case .failure: print("Happiness V1 not available at the moment .(")   }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 {   switch  {   case .success: print("Happiness V2 delivered .)")   case .failure: print("Happiness V2 not available at the moment .(")   }}

行strong_retain%0:$Test,loc“Test.swift”:9:16,范围3 // ID:%3告诉我们编译器为$Test(定义为self)做强引用,此引用存在于范围3(即功能A)并且在离开范围3时未释放.

第二个函数closureA处理self的可选引用.它在代码中表示为%2 = alloc_Box $@ sil_weak可选< Test>,var,名称“self”,loc“Test.swift”:13:38,范围8 //用户:?,?,%9,% 3.

因此,如果嵌套函数访问self中定义的某些属性,那么嵌套函数将保留对self的强引用.编译器不会通知它(Swift 3.0.1).

为了避免这种行为,我们只需要使用闭包而不是嵌套函数.然后编译器将通知自我使用情况.

原始示例可以重新表示如下:

[+++] 总结

以上是内存溢出为你收集整理的Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?全部内容,希望文章能够帮你解决Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?_app_内存溢出

Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?

Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?,第1张

概述需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2. 在方法loadHappinessV1中: >如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化 >为了防止编译器错误,我指定对self的弱引用. 在方 需要你的帮助来理解当从闭包中调用嵌套函数时 Swift捕获语义是如何工作的.所以,我有两个方法loadHappinessV1和loadHappinessV2.

在方法loadHappinessV1中:

>如果未指定self,编译器会引发错误:error:在闭包中对属性’callbackQueue’的引用需要显式的’self’.使捕获语义显式化
>为了防止编译器错误,我指定对self的弱引用.

在方法loadHappinessV2中:

>我决定引入两个嵌套函数并简化 *** 作的“主体”.
>编译器不会引发有关捕获语义的错误.

为什么在方法loadHappinessV2编译器中不会引发有关捕获语义的错误?是否未捕获嵌套函数(以及变量callbackQueue)?

谢谢!

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         func completeWithFailure() {            callbackQueue.async { completion(.failure) }         }         func completeWithSuccess() {            callbackQueue.async { completion(.success) }         }        let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {                completeWithSuccess()            } else {                completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch 
class Test {    var bar: Int = 0    func functionA() -> (() -> ()) {        func nestedA() {            bar += 1        }        return nestedA    }    func closureA() -> (() -> ()) {        let nestedClosureA = { [uNowned self] () -> () in            self.bar += 1        }        return nestedClosureA    }}
{ case .success: print("Happiness V1 delivered .)") case .failure: print("Happiness V1 not available at the moment .(") }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 { switch
sil_scope 2 { loc "Test.swift":5:10 parent @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 3 { loc "Test.swift":10:5 parent 2 }// Test.functionA() -> () -> ()sil hIDden @Test.Test.functionA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %4,%3,%1bb0(%0 : $Test):  deBUG_value %0 : $Test,let,name "self",argno 1,loc "Test.swift":5:10,scope 2 // ID: %1  // function_ref Test.(functionA() -> () -> ()).(nestedA #1)() -> ()  %2 = function_ref @Test.Test.(functionA () -> () -> ()).(nestedA #1) () -> () : $@convention(thin) (@owned Test) -> (),loc "Test.swift":9:16,scope 3 // user: %4  strong_retain %0 : $Test,scope 3 // ID: %3  %4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> (),scope 3 // user: %5  return %4 : $@callee_owned () -> (),loc "Test.swift":9:9,scope 3 // ID: %5}
{ case .success: print("Happiness V2 delivered .)") case .failure: print("Happiness V2 not available at the moment .(") }}
解决方法 我找到了一些解释如何使用嵌套函数捕获语义.资料来源: Nested functions and reference capturing.

考虑以下示例:

sil [transparent] [fragile] @Swift.Int.init (_builtinintegerliteral : Builtin.Int2048) -> Swift.Int : $@convention(method) (Builtin.Int2048,@thin Int.Type) -> Intsil_scope 6 { loc "Test.swift":12:10 parent @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () }sil_scope 7 { loc "Test.swift":17:5 parent 6 }sil_scope 8 { loc "Test.swift":15:9 parent 7 }// Test.closureA() -> () -> ()sil hIDden @Test.Test.closureA () -> () -> () : $@convention(method) (@guaranteed Test) -> @owned @callee_owned () -> () {// %0                                             // users: %5,%4,loc "Test.swift":12:10,scope 6 // ID: %1  %2 = alloc_Box $@sil_weak Optional<Test>,loc "Test.swift":13:38,scope 8 // users: %13,%11,%9,%3  %3 = project_Box %2 : $@Box @sil_weak Optional<Test>,scope 8 // users: %10,%6  strong_retain %0 : $Test,scope 8 // ID: %4  %5 = enum $Optional<Test>,#Optional.some!enumelt.1,%0 : $Test,scope 8 // users: %7,%6  store_weak %5 to [initialization] %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %6  release_value %5 : $Optional<Test>,scope 8 // ID: %7  // function_ref Test.(closureA() -> () -> ()).(closure #1)  %8 = function_ref @Test.Test.(closureA () -> () -> ()).(closure #1) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),loc "Test.swift":13:30,scope 8 // user: %11  strong_retain %2 : $@Box @sil_weak Optional<Test>,scope 8 // ID: %9  mark_function_escape %3 : $*@sil_weak Optional<Test>,scope 8 // ID: %10  %11 = partial_apply %8(%2) : $@convention(thin) (@owned @Box @sil_weak Optional<Test>) -> (),scope 8 // users: %14,%12  deBUG_value %11 : $@callee_owned () -> (),name "nestedClosureA",loc "Test.swift":13:13,scope 7 // ID: %12  strong_release %2 : $@Box @sil_weak Optional<Test>,loc "Test.swift":15:9,scope 7 // ID: %13  return %11 : $@callee_owned () -> (),loc "Test.swift":16:9,scope 7 // ID: %14}

编译器提醒我们保持函数closureA的所有权.但是没有说明在功能函数A中捕获自我的任何信息.

让我们看看Swift中间语言(SIL):
xcrun swiftc -emit-silgen Test.swift | xcrun swift-demangle> Test.silgen

import PlaygroundSupportimport CocoaPlaygroundPage.current.needsIndefiniteExecution = truestruct Happiness {   final class Net {      enum LoadResult {         case success         case failure      }      private var callbackQueue: dispatchQueue      private lazy var operationQueue = OperationQueue()      init(callbackQueue: dispatchQueue) {         self.callbackQueue = callbackQueue      }      func loadHappinessV1(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         let hapynessOp = BlockOperation { [weak self] in            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               // callbackQueue.async { completion(.success) } // Compile error               self?.callbackQueue.async { completion(.success) }            } else {               // callbackQueue.async { completion(.failure) } // Compile error               self?.callbackQueue.async { completion(.failure) }            }         }         operationQueue.addOperation(hapynessOp)      }      func loadHappinessV2(completion: @escaPing (LoadResult) -> VoID) {         operationQueue.cancelAllOperations()         // Closure used instead of nested function.         let completeWithFailure = { [weak self] in            self?.callbackQueue.async { completion(.failure) }         }         // Closure used instead of nested function.         let completeWithSuccess = { [weak self] in            self?.callbackQueue.async { completion(.success) }         }         let hapynessOp = BlockOperation {            let hapynessGeneratorValue = arc4random_uniform(10)            if hapynessGeneratorValue % 2 == 0 {               completeWithSuccess()            } else {               completeWithFailure()            }         }         operationQueue.addOperation(hapynessOp)      }   }}// Usagelet happinessNetV1 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV1.loadHappinessV1 {   switch  {   case .success: print("Happiness V1 delivered .)")   case .failure: print("Happiness V1 not available at the moment .(")   }}let happinessNetV2 = Happiness.Net(callbackQueue: dispatchQueue.main)happinessNetV2.loadHappinessV2 {   switch  {   case .success: print("Happiness V2 delivered .)")   case .failure: print("Happiness V2 not available at the moment .(")   }}

行strong_retain%0:$Test,loc“Test.swift”:9:16,范围3 // ID:%3告诉我们编译器为$Test(定义为self)做强引用,此引用存在于范围3(即功能A)并且在离开范围3时未释放.

第二个函数closureA处理self的可选引用.它在代码中表示为%2 = alloc_Box $@ sil_weak可选< Test>,var,名称“self”,loc“Test.swift”:13:38,范围8 //用户:?,?,%9,% 3.

因此,如果嵌套函数访问self中定义的某些属性,那么嵌套函数将保留对self的强引用.编译器不会通知它(Swift 3.0.1).

为了避免这种行为,我们只需要使用闭包而不是嵌套函数.然后编译器将通知自我使用情况.

原始示例可以重新表示如下:

总结

以上是内存溢出为你收集整理的Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?全部内容,希望文章能够帮你解决Swift:从闭包调用嵌套函数时捕获语义.为什么编译器不会引发错误?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1017767.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存