Swift 闭包在作为 Objective-C 块调用时崩溃

2023-12-25

在我的项目中,我同时拥有 Objective-C 和 Swift 代码。我有一些对象的属性包含用于清理某些 UITableView 配置的块。在 Objective-C 中使用它可以工作,但在使用 Swift 时会崩溃。

我已将问题减少到尽可能小,同时仍然可重现。

// in Objective-C
@interface MyClass : NSObject
@property (copy, nonatomic) NSString* (^block)();
- (NSString *)callTheBlock;
@end

@implementation MyClass
- (NSString *)callTheBlock {
    if (self.block) {
        return self.block();
    } else {
        return @"There is no spoon";
    }
}
@end

// In Swift
// I actually have this in my AppDelegate to run when the app starts, but that shouldn't matter

class AppDelegate: UIResponder, UIApplicationDelegate {
    var myClass: MyClass?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    self.myClass = MyClass()
    self.myClass?.block = { () -> String in 
        NSLog("In Closure")
        var string = "String From Closure" // <-- "po string" correctly prints the string
        return string // <-- This is where it crashes
    }

    let output = self.myClass?.callTheBlock()
    NSLog("\(output)")
...

}

我最终得到EXC_BAD_ACCESS,所以我猜测这与不应该发布的内容有关,但我不知道我做错了什么。

堆栈跟踪非常少:

* thread #1: tid = 0x4a8b6a, 0xbff2d9c8, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0xbff2d9c8)
  * frame #0: 0xbff2d9c8
    frame #1: 0xbff2d9e0

但是,如果我更改块以想要一个字符串作为参数:

// MyClass 
@property (copy, nonatomic) NSString* (^block)(NSString *string);

// Using it in Swift
self.myClass?.block = { (inString: String!) -> String in 
    NSLog("In Closure")
    var string = "String From Closure"
    return string
}

我得到了更能说明问题的堆栈跟踪:

* thread #1: tid = 0x4a9a38, 0x01b07e63 libobjc.A.dylib`objc_release + 19, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x40000013)
    frame #0: 0x01b07e63 libobjc.A.dylib`objc_release + 19
  * frame #1: 0x0005e442 MyApp`MyApp.AppDelegate.(inString=Some) -> (ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool).(closure #1) + 594 at AppDelegate.swift:22
    frame #2: 0x0005e4ad MyApp`reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 77 at AppDelegate.swift:19
    frame #3: 0x0005cbaa MyApp`partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 90 at AppDelegate.swift:0
    frame #4: 0x0005e5e7 MyApp`reabstraction thunk helper from @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 71 at AppDelegate.swift:19
    frame #5: 0x0005ce64 MyApp`partial apply forwarder for reabstraction thunk helper from @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 132 at AppDelegate.swift:0
    frame #6: 0x0005e7ee MyApp`reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_unowned @objc_block (@unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSString>) -> (@autoreleased Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSString>) + 478 at AppDelegate.swift:19
    frame #7: 0x0008fa3f MyApp`-[MyClass callTheBlock](self=0x7beadc50, _cmd=0x000edee6) + 143 at MyClass.m:38
    frame #8: 0x0005bcf8 MyApp`MyApp.AppDelegate.application (application=0x7c160390, launchOptions=None, self=0x7c162d50)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool + 1544 at AppDelegate.swift:24
    frame #9: 0x0005cf55 MyApp`@objc MyApp.AppDelegate.application (MyApp.AppDelegate)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool + 101 at AppDelegate.swift:0
    frame #10: 0x0090d14f UIKit`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 309
    frame #11: 0x0090daa1 UIKit`-[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1810
    frame #12: 0x00912667 UIKit`-[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
    frame #13: 0x00926f92 UIKit`-[UIApplication handleEvent:withNewEvent:] + 3517
    frame #14: 0x00927555 UIKit`-[UIApplication sendEvent:] + 85
    frame #15: 0x00914250 UIKit`_UIApplicationHandleEvent + 683
    frame #16: 0x03b9df02 GraphicsServices`_PurpleEventCallback + 776
    frame #17: 0x03b9da0d GraphicsServices`PurpleEventCallback + 46
    frame #18: 0x01cf6ca5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
    frame #19: 0x01cf69db CoreFoundation`__CFRunLoopDoSource1 + 523
    frame #20: 0x01d2168c CoreFoundation`__CFRunLoopRun + 2156
    frame #21: 0x01d209d3 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #22: 0x01d207eb CoreFoundation`CFRunLoopRunInMode + 123
    frame #23: 0x00911d9c UIKit`-[UIApplication _run] + 840
    frame #24: 0x00913f9b UIKit`UIApplicationMain + 1225
    frame #25: 0x0005dbae MyApp`top_level_code + 78 at AppDelegate.swift:12
    frame #26: 0x0005dbeb MyApp`main + 43 at AppDelegate.swift:0
    frame #27: 0x024e3701 libdyld.dylib`start + 1

编辑:我最初认为它与异步调用有关,但之后可以像这样直接调用它,因此我修复了代码和堆栈跟踪以反映这一点。


我在弹出文档的帮助下弄清楚了! 当处理 Objective-C 时,大多数事情都需要!。我很确定这是因为 Objective-C 没有像 Swift 那样的可选概念。

而不是将我的闭包定义为:

... self.myClass?.block = { (inString: String!) -> String in ...

当将其更改为:

... self.myClass?.block = { (inString: String!) -> String! in ...

这是有道理的,因为这是弹出文档中推荐的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift 闭包在作为 Objective-C 块调用时崩溃 的相关文章

  • 恢复从未付款过的用户的应用内购买

    我正在尝试在我的应用程序中测试应用程序内购买 当我与购买了应用程序内购买的测试用户恢复应用程序内购买时 一切正常 但是当我尝试与用户恢复应用内购买时didn t在我期望框架调用以下方法之前进行应用内购买 paymentQueue resto
  • CoreMediaIO,错误更新的属性 kCMIODevicePropertyDeviceIsRunningSomewhere

    当某些进程开始使用相机时 我需要接收一个事件 我通过 CMIOObjectGetPropertyData 完成此操作 但它不能正常工作 只有第一次访问时才是正确的值 我还尝试使用 CMIOObjectAddPropertyListenerB
  • PhoneGap/Cordova:如何使用cookies(iOS)?

    我有一个适用于 iOS 的 PhoneGap Corodova 项目 在 iOS 模拟器上构建时 我使用了 Jquery Cookies 它们很好 但是 既然我的设备上有该应用程序用于测试 它们就不再工作了 我猜这只是 iOS 不支持的东西
  • 编码的 nsdata utf8 json,在 ios 中带有重音字符

    我向网络服务器发出一个发布请求 该服务器用 JSON 回答我 这是响应的标头 Cache Control private Content Length 826 Content Type application json charset ut
  • 如何从 GCD (DispatchQueue) 转换为 Swift async/await?

    我正在关注斯坦福大学的 CS193p 开发 iOS 应用程序在线课程 它使用 Grand Central Dispatch GCD API 来演示多线程 但他们指出 自 WWDC 2021 起 GCD 已大部分被 Swift 新的内置异步
  • BUG - 在 IOS 中没有选择标签的完成按钮

    我正在使用最新的离子并有一个简单的选择标签
  • iOS 8 支持动态链接吗?

    直到 iOS7 之前 出于安全考虑 Apple 都不支持动态链接 开发人员之间的代码重用通常依赖于静态库 这些静态库是作为应用程序可执行文件的一部分构建的 在 iOS8 中引入扩展似乎稍微改变了这一点 因为扩展是单独的可执行文件 扩展及其包
  • 创建类似于邮件应用程序菜单的 iPhone 弹出菜单

    当您想要回复消息时 我想创建一个类似于邮件应用程序中的弹出菜单 我在多个应用程序中看到过这一点 所以我不确定框架中是否内置了某些内容或一些示例代码 在 Swift 中创建操作表 代码已使用 Swift 5 进行测试 从 iOS 8 开始 U
  • NSHTTPCookieStorage 是否跨应用程序持续存在?

    所以我只是好奇 NSHTTPCookieStorage 是否跨应用程序持久存在 或者仅在当前应用程序本地 我希望在另一个应用程序中收集的一些 cookie 可以在搜索应用程序中访问 是这样的吗 谢谢 PS 这是在 iPhone 或 iPad
  • Swift - 本地通知不会被触发

    我正在 Swift 3 中编码 我只是想发送通知now没有任何延迟或间隔 然而 通知永远不会被触发 这是我的代码 视图控制器代码 import UserNotifications class HomeViewController UIVie
  • 部署目标是什么意思?

    这是我假设的一个非常简单的问题 有人可以告诉我部署目标是什么意思吗 如果我选择 iOS 10 是否意味着只有 iOS 10 的用户才能下载该应用程序 选择较低的部署目标是否不好 另外 继续部署目标 是否不建议在较低的部署目标上运行 假设您已
  • CLLocation Manager如何在一定距离后更新

    我正在使用 CLLocationManager didupdatelocations 如下所示 func locationManager manager CLLocationManager didUpdateLocations locati
  • tableView.dequeueReusableCellWithIdentifier() 导致应用程序挂起

    原帖 我们最近将我们的应用程序转换为 Swift 2 0 和 iOS9 我看到的一个奇怪的问题是调用 tableView dequeueReusableCellWithIdentifier 会导致应用程序挂在模拟器中 The code fu
  • 允许的 APNS 持续连接数量是多少?

    我正在尝试编写服务器端代码来为我的应用程序发送推送通知 根据 Apple 的建议 我计划保留连接并根据需要发送推送通知 Apple 还允许打开和保留多个并行连接以发送推送通知 您可以与同一网关或多个网关实例建立多个并行连接 为此 我想维护一
  • 当我从我转向的视图控制器返回时,为什么我的 UITableView 的格式完全出错了?

    我有一个UITableView使用自定义单元格 其中有一些标签可以动态决定单元格的高度 当我点击一个单元格并转到一个新的视图控制器时 返回后所有单元格的格式完全混乱 我无法弄清楚是什么导致了它 这是细胞通常的样子 我对它们设置了一些非常基本
  • Haskell 排列库函数 - 请澄清一下?

    这是代码permutationsHaskell 中的函数Data List module permutations a gt a permutations xs0 xs0 perms xs0 where perms perms t ts i
  • UITextView 动画更改框架不会动画文本重新分配

    我有一个 UITextView 我试图在用户点击按钮时为框架的变化设置动画 基本上 文本视图会变大以适应屏幕 以便可以显示更多文本 然后当用户再次点击按钮时 它会缩小到原始框架 我使用块执行动画 如下所示 if isDisplayingDe
  • 当应用程序退出活动状态时,MPMovies PlayerViewController 被解雇

    当我将 iPhone 设置为睡眠状态 切换到另一个应用程序等 然后再次返回时 之前的可见内容MPMoviePlayerViewController 提出与presentMoviePlayerViewControllerAnimated 已经
  • 最近打开的应用程序[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有什么方法可以获取最近打开的应用程序 例如 4 个 的列表吗 如果是这样 怎么办 可可麦克 看看LaunchServices LSSh
  • 自定义字体显示在 IB 中,但不显示在模拟器中

    我已经设置了一个UITextView and a UILabel使用自定义字体 它是垂直镜像的蒙古文字体 但我还添加了英文文本 以便您可以看到效果 这些文字显示在 Interface Builder 中 但在模拟器中大部分字符都在UITex

随机推荐