微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift 库导致 iPhone 上的 Objective-C 应用程序随机崩溃

如何解决Swift 库导致 iPhone 上的 Objective-C 应用程序随机崩溃

我有一个在 Objective-C iOS 应用中使用时崩溃的 Swift 库。应用商店中大约 3% 的用户的应用程序崩溃。不过用户群很大,所以绝对数量很多。删除库后,不会发生崩溃。所有崩溃都发生在 iOS 14 上,其中 95% 的设备是 iPhone。

我无权访问应用程序的源代码,也无法调试它。此外,我无法按需在手机上重现此问题。我让应用程序随机崩溃。

Crashlytics 指向我们库中的 UrlBuilder 类。我把它贴在下面。

struct ExternalConfigConstants {
    static let configJsonURL = "https://cdn.mycompany.com/sdk/live/%@/config.json"
}


protocol ConfigurationUrlBuilder {
    func getExternalConfigUrl() throws -> String
}

class UrlBuilder: ConfigurationUrlBuilder {
    func getExternalConfigUrl() throws -> String {
        if let appName = ExternalConfigurationManagerBuilder.appName {
            return String(format: ExternalConfigConstants.configJsonURL,appName)
        } else {
            throw ConfigurationParsingError.undefinedAppName
        }
    }
}

了解 UrlBuilder 从何处获取 appName 属性可能很有用。这是一个存储类型属性。它的值由应用开发者传递。

public class ExternalConfigurationManagerBuilder {
    public static var appName: String?
}
@objc public class MyAPI: NSObject {

    @objc public static let instance = MyAPI()

    @objc public func setAppName(appName: String) {
        ExternalConfigurationManagerBuilder.appName = appName
    }
}

这是应用开发者通过 appName 的方式:

[MyAPI.instance setAppNameWithAppName:@"clientApp"];

然后在稍后的某个时刻 UrlBuilder.getExternalConfigUrl() 被库调用

MyAPIExternalConfigurationManagerBuilder/UrlBuilder 类被打包在两个不同的 Pod 中。我们使用 CocoaPods 来分发库。

错误消息提到“UrlBuilder 的类型元数据访问器”。我读过关于类型元数据访问器的文章,它们似乎是编译器生成函数,供运行时用于类型检查。

在调查此问题时,我们发现我们的代码存在以下问题,但是我们无法将这些问题中的任何一个与崩溃联系起来:

  1. 我们没有像 Swift 书建议的那样给存储类型属性 appName 一个认值。我们依赖于应用开发者在调用 UrlBuilder 之前为其分配一个

  2. ExternalConfigurationManagerBuilder 类用作单例,但不遵循将实例分配给静态属性的推荐模式

  3. 当传递一个 int 而不是一个字符串时,我们使用的字符串插值方法可能会崩溃。我已经与应用开发者核实过,他们确认他们正在传递一个字符串。

我们还尝试将手机切换到不同的语言和区域,这些似乎不会导致崩溃。

这些崩溃的原因可能是什么? 什么可以帮助我隔离问题并按需重现它?

这里是日志:

Crashed: NSOperationQueue 0x104d61d10 (QOS: UNSPECIFIED)
0  libobjc.A.dylib                0x1a4bba128 lookUpImpOrForward + 76
1  libobjc.A.dylib                0x1a4ba4524 _objc_msgSend_uncached + 68
2  CoreFoundation                 0x18fad45d8 _CFErrorcopyUserInfoKeyFromUserInfo + 24
3  CoreFoundation                 0x18fad469c _CFErrorcopyUserInfoKey + 28
4  CoreFoundation                 0x18fad4310 _CFErrorCreateLocalizedDescription + 164
5  Foundation                     0x190e08948 -[NSError localizedDescription] + 88
6  clientApp-ios                  0x103072b60 type Metadata accessor for UrlBuilder + 4342754144 (<compiler-generated>:4342754144)
7  clientApp-ios                  0x103072260 type Metadata accessor for UrlBuilder + 4342751840 (<compiler-generated>:4342751840)
8  clientApp-ios                  0x103076624 type Metadata accessor for UrlBuilder + 4342769188 (<compiler-generated>:4342769188)
9  clientApp-ios                  0x103076408 type Metadata accessor for UrlBuilder + 4342768648 (<compiler-generated>:4342768648)
10 Foundation                     0x190edc850 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 24
11 Foundation                     0x190dc9740 -[NSBlockOperation main] + 104
12 Foundation                     0x190edeca4 __NSOPERATION_IS_INVOKING_MAIN__ + 24
13 Foundation                     0x190dc93c8 -[NSOperation start] + 808
14 Foundation                     0x190edf74c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 24
15 Foundation                     0x190edf1d4 __NSOQSchedule_f + 184
16 libdispatch.dylib              0x18f78ffb8 _dispatch_block_async_invoke2 + 148
17 libdispatch.dylib              0x18f781db0 _dispatch_client_callout + 20
18 libdispatch.dylib              0x18f78512c _dispatch_continuation_pop + 416
19 libdispatch.dylib              0x18f784854 _dispatch_async_redirect_invoke + 592
20 libdispatch.dylib              0x18f79293c _dispatch_root_queue_drain + 356
21 libdispatch.dylib              0x18f793120 _dispatch_worker_thread2 + 116
22 libsystem_pthread.dylib        0x1db63d7d8 _pthread_wqthread + 216
23 libsystem_pthread.dylib        0x1db64476c start_wqthread + 8

一个日志:

Fatal Exception: NSinvalidargumentexception
0  CoreFoundation                 0x184d8986c __exceptionPreprocess
1  libobjc.A.dylib                0x199da4c50 objc_exception_throw
2  CoreFoundation                 0x184c9095c -[NSOrderedSet initWithSet:copyItems:]
3  CoreFoundation                 0x184d8c438 ___forwarding___
4  CoreFoundation                 0x184d8e740 _CF_forwarding_prep_0
5  clientApp-ios                  0x1031ceb60 type Metadata accessor for UrlBuilder (<compiler-generated>)
6  clientApp-ios                  0x1031ce260 type Metadata accessor for UrlBuilder (<compiler-generated>)
7  clientApp-ios                  0x1031d2624 type Metadata accessor for UrlBuilder (<compiler-generated>)
8  clientApp-ios                  0x1031d2408 type Metadata accessor for UrlBuilder (<compiler-generated>)
9  Foundation                     0x1860d8850 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__
10 Foundation                     0x185fc5740 -[NSBlockOperation main]
11 Foundation                     0x1860daca4 __NSOPERATION_IS_INVOKING_MAIN__
12 Foundation                     0x185fc53c8 -[NSOperation start]
13 Foundation                     0x1860db74c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__
14 Foundation                     0x1860db1d4 __NSOQSchedule_f
15 libdispatch.dylib              0x18498bfb8 _dispatch_block_async_invoke2
16 libdispatch.dylib              0x18497ddb0 _dispatch_client_callout
17 libdispatch.dylib              0x18498112c _dispatch_continuation_pop
18 libdispatch.dylib              0x184980854 _dispatch_async_redirect_invoke
19 libdispatch.dylib              0x18498e93c _dispatch_root_queue_drain
20 libdispatch.dylib              0x18498f120 _dispatch_worker_thread2
21 libsystem_pthread.dylib        0x1d08397d8 _pthread_wqthread
22 libsystem_pthread.dylib        0x1d084076c start_wqthread

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。