在存储字符串值时如何无条件解决BridgeFromObjectiveC崩溃? (WKInterfaceDevice.current()。name)

问题描述 投票:0回答:1

我在Apple Watch应用中突然出现unconditionallyBridgeFromObjectiveC崩溃。我无法在本地复制它,也从未通过常规使用在测试设备上遇到它。这是有关异常的信息:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000224c58b0
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [653]

崩溃报告显示它正在此代码的第二行:

let name: String
name = WKInterfaceDevice.current().name

(为了方便阅读,我将它们放在单独的行中)

我不是很熟悉Objective-C,或者与Objective-C价值观有关的事情可能失败,但是根据我在互联网上发现的情况,这是我的猜测:

即使the API says WKInterfaceDevice.current().nameString而不是String?name在某些情况下实际上还是一个nil值。

作为一种可能的解决方案,我认为应该使用name: String而不是name: String?,然后确保它以后不为零。这有意义吗?这将有助于解决该问题,还是可能会因为尝试以WKInterfaceDevice.current().name类型的常量存储String?而仍然崩溃?我首先应该对WKInterfaceDevice.current().name做其他安全检查吗?

此崩溃发生的次数不多(在大约5天内,至少有7台设备在大约5000台设备中,大约5天之内),但这是我最新版本的应用程序中最频繁发生的崩溃,因此,我尝试将其作为学习的机会,使我的应用程序更强大。我想也许这可能是WatchKit中的问题,而不是我的代码有问题?还是只能使用Objective-C检查和解决的问题?

objective-c swift watchkit
1个回答
0
投票

尽管API表示WKInterfaceDevice.current().nameString而不是String?,但在某些情况下name实际上是nil值。

不能为nilname是声明为:

的属性
var name: String { get }

它可以是一个空字符串,但不能是nil(Swift上下文)。和Objective-C:

@property(nonatomic, readonly, copy) NSString *name;

[NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END封装,实际上表示:

@property(nonatomic, readonly, copy) NSString * _Nonnull safeName;

阅读Nullability and Objective-C以了解它如何影响Objective-C-> Swift。

实际上,在Objective-C上下文中可以是nil,但那时它违反了_Nonnull合同。

作为一种可能的解决方案,我认为我应该使用name: String而不是name: String?

即使您可以做到,我认为也不会有所帮助。假设您有以下方法1

- (NSString * _Nonnull)canNotBeNilNothing {
    return nil;
}

在Swift中使用:

let name: String? = WKInterfaceDevice.current().canNotBeNilNothing();
print("\(String(describing: name))")

您仍然得到Optional(""),而不是nil。可以预见,因为有这个_Nonnull(它违反了合同,但这是另外一回事了。)>

如果确实确定它可以在Objective-C中返回nil,则可以创建这样的内容:

- (NSString * _Nullable)maybeName {
    return [self name];
}

然后您可以在Swift中使用String?,如果nil将返回[self name],则它可以变为nil。>

您的问题的可能原因

  • 在WatchKit中的某个地方发现错误(不正确的可空性注释,...)
  • 其他]

    我不确定发生了什么,因为我没有看到堆栈跟踪。

  • 可能的解决方案

WatchKit和Objective-C问题(引发异常)?它可以用Objective-C中的以下包装器修复:

- (NSString * _Nullable)maybeName {
    @try {
        return [self name];
    }
    @catch (NSException *exception) {
        // Return nil or handle it your way
        return nil;
    }
}

桥接问题(不正确的为空性?它可能可以通过Swift中的以下代码修复:

extension WKInterfaceDevice {
    var maybeName: String? {
        self.perform(#selector(getter: WKInterfaceDevice.name))?.takeRetainedValue() as! String?
    }
}

1

通常,您应该大致查看nullablenonnull当前使用断言或异常的方式:违反合同是程序员错误。特别是,返回值是由您控制的东西,因此,除非返回值是向后兼容的,否则切勿为非空返回类型返回nil。 (Nullability and Objective-C
© www.soinside.com 2019 - 2024. All rights reserved.