iOS 今天扩展程序崩溃
iOS Today Extension Crashing
我们最近在我们的应用程序中添加了 Today Extension。
它是一个简单的 tableView 扩展,用于从我们的服务器加载数据,用 Swift 编写。
但是在扩展对我们的用户在线后,我们从 Crashlytics
收到了大量的崩溃数据,Apple 也报告了同样的崩溃问题。
但是,我们无法重现崩溃,甚至找不到崩溃的原因,因为在系统调用的 widgetPerformUpdateWithCompletionHandler
方法上崩溃。
以下是崩溃日志的详细信息,部分信息已被替换。
Crashed: com.apple.main-thread
0 MyAppWidget 0x100091d8c MyAppWidgetViewController.(widgetPerformUpdateWithCompletionHandler((NCUpdateResult) -> ()) -> ()).(closure #1) (MyAppWidgetViewController.swift)
1 MyAppKit 0x100603ab4 partial apply for thunk (PostService.swift)
2 MyAppKit 0x100626080 ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:35)
3 MyAppKit 0x1006258d4 partial apply for ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift)
4 MyAppKit 0x100626b34 ServiceRequestPerfomer.((request in _3C50B415180DDC893FFCB75CD7EE7019)(A, complete : (response : Response?, error : NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:144)
5 Moya 0x1004b7468 MoyaProvider.(requestNormal(A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> Cancellable).(closure #1).(closure #1) (Moya.swift:229)
6 Moya 0x1004b8968 MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
7 Moya 0x1004b57b8 partial apply for MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
8 Alamofire 0x1002cff64 Request.(response(queue : OS_dispatch_queue?, completionHandler : (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> ()) -> Self).(closure #1).(closure #1) (ResponseSerialization.swift)
9 libdispatch.dylib 0x1819e14bc _dispatch_call_block_and_release + 24
10 libdispatch.dylib 0x1819e147c _dispatch_client_callout + 16
11 libdispatch.dylib 0x1819e6b84 _dispatch_main_queue_callback_4CF + 1844
12 CoreFoundation 0x181f4cd50 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
13 CoreFoundation 0x181f4abb8 __CFRunLoopRun + 1628
14 CoreFoundation 0x181e74c50 CFRunLoopRunSpecific + 384
15 GraphicsServices 0x18375c088 GSEventRunModal + 180
16 UIKit 0x18715e088 UIApplicationMain + 204
17 libxpc.dylib 0x181c38ce0 _xpc_objc_main + 784
18 libxpc.dylib 0x181c3a9dc xpc_main + 200
19 Foundation 0x182a57d60 service_connection_handler + 170
20 PlugInKit 0x18929ac48 -[PKService run] + 544
21 PlugInKit 0x18929a8dc +[PKService main] + 56
22 PlugInKit 0x18929ac6c +[PKService _defaultRun:arguments:] + 20
23 libextension.dylib 0x18286a058 NSExtensionMain + 64
24 libdispatch.dylib 0x181a128b8 (Missing)
以及widgetPerformUpdateWithCompletionHandler
的代码
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
let options: [String: AnyObject] = [DCKPostPopularAttributeName : true.stringValue,
DCKPaginationLimitAttributeName : 5]
postService.posts(options: options) { (posts, error) in
let historyPosts = self.userDefaults.arrayForKey(MyAppWidgetViewController.WidgetPostReadIdentifier) as? [UInt]
if let historyPosts = historyPosts {
self.posts = posts!.filter({ (Post) -> Bool in
return !historyPosts.contains(Post.id)
})
} else {
self.posts = posts!
}
self.tableView.reloadData()
self.tableView.hidden = false;
self.loadingLabel?.hidden = true
self.activityIndicator?.stopAnimating()
let contentSize = self.tableView.contentSize
self.preferredContentSize = CGSizeMake(CGRectGetWidth(self.view.frame), contentSize.height);
self.loadMorePostsIfNeeded()
}
completionHandler(NCUpdateResult.NewData)
}
奇怪的是:
我们在正常使用 Today 扩展时没有遇到崩溃问题(如果今天扩展崩溃,它应该显示 Unable to load
)
我们没有收到用户报告的任何问题,今天扩展程序无法正常工作。
我们在我们的设备上发现了相同的崩溃日志,但今天的扩展正常工作,如 1.
所述。还有,记录崩溃日志的时间,我没有使用我的 phone!
所以我们猜测这是一次“假的”崩溃,记录了崩溃,但扩展程序并没有真正崩溃。
有人面临同样的问题吗?
谢谢!
回答我自己的问题,
@matt 是对的,现在我只在数据获取任务完成时才调用 completionHandler
,而不是总是在 widgetPerformUpdateWithCompletionHandler
方法的最后调用 completionHandler
。
我没有再收到崩溃,问题已解决!
我们最近在我们的应用程序中添加了 Today Extension。
它是一个简单的 tableView 扩展,用于从我们的服务器加载数据,用 Swift 编写。
但是在扩展对我们的用户在线后,我们从 Crashlytics
收到了大量的崩溃数据,Apple 也报告了同样的崩溃问题。
但是,我们无法重现崩溃,甚至找不到崩溃的原因,因为在系统调用的 widgetPerformUpdateWithCompletionHandler
方法上崩溃。
以下是崩溃日志的详细信息,部分信息已被替换。
Crashed: com.apple.main-thread
0 MyAppWidget 0x100091d8c MyAppWidgetViewController.(widgetPerformUpdateWithCompletionHandler((NCUpdateResult) -> ()) -> ()).(closure #1) (MyAppWidgetViewController.swift)
1 MyAppKit 0x100603ab4 partial apply for thunk (PostService.swift)
2 MyAppKit 0x100626080 ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:35)
3 MyAppKit 0x1006258d4 partial apply for ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift)
4 MyAppKit 0x100626b34 ServiceRequestPerfomer.((request in _3C50B415180DDC893FFCB75CD7EE7019)(A, complete : (response : Response?, error : NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:144)
5 Moya 0x1004b7468 MoyaProvider.(requestNormal(A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> Cancellable).(closure #1).(closure #1) (Moya.swift:229)
6 Moya 0x1004b8968 MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
7 Moya 0x1004b57b8 partial apply for MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
8 Alamofire 0x1002cff64 Request.(response(queue : OS_dispatch_queue?, completionHandler : (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> ()) -> Self).(closure #1).(closure #1) (ResponseSerialization.swift)
9 libdispatch.dylib 0x1819e14bc _dispatch_call_block_and_release + 24
10 libdispatch.dylib 0x1819e147c _dispatch_client_callout + 16
11 libdispatch.dylib 0x1819e6b84 _dispatch_main_queue_callback_4CF + 1844
12 CoreFoundation 0x181f4cd50 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
13 CoreFoundation 0x181f4abb8 __CFRunLoopRun + 1628
14 CoreFoundation 0x181e74c50 CFRunLoopRunSpecific + 384
15 GraphicsServices 0x18375c088 GSEventRunModal + 180
16 UIKit 0x18715e088 UIApplicationMain + 204
17 libxpc.dylib 0x181c38ce0 _xpc_objc_main + 784
18 libxpc.dylib 0x181c3a9dc xpc_main + 200
19 Foundation 0x182a57d60 service_connection_handler + 170
20 PlugInKit 0x18929ac48 -[PKService run] + 544
21 PlugInKit 0x18929a8dc +[PKService main] + 56
22 PlugInKit 0x18929ac6c +[PKService _defaultRun:arguments:] + 20
23 libextension.dylib 0x18286a058 NSExtensionMain + 64
24 libdispatch.dylib 0x181a128b8 (Missing)
以及widgetPerformUpdateWithCompletionHandler
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
let options: [String: AnyObject] = [DCKPostPopularAttributeName : true.stringValue,
DCKPaginationLimitAttributeName : 5]
postService.posts(options: options) { (posts, error) in
let historyPosts = self.userDefaults.arrayForKey(MyAppWidgetViewController.WidgetPostReadIdentifier) as? [UInt]
if let historyPosts = historyPosts {
self.posts = posts!.filter({ (Post) -> Bool in
return !historyPosts.contains(Post.id)
})
} else {
self.posts = posts!
}
self.tableView.reloadData()
self.tableView.hidden = false;
self.loadingLabel?.hidden = true
self.activityIndicator?.stopAnimating()
let contentSize = self.tableView.contentSize
self.preferredContentSize = CGSizeMake(CGRectGetWidth(self.view.frame), contentSize.height);
self.loadMorePostsIfNeeded()
}
completionHandler(NCUpdateResult.NewData)
}
奇怪的是:
我们在正常使用 Today 扩展时没有遇到崩溃问题(如果今天扩展崩溃,它应该显示
Unable to load
)我们没有收到用户报告的任何问题,今天扩展程序无法正常工作。
我们在我们的设备上发现了相同的崩溃日志,但今天的扩展正常工作,如
1.
所述。还有,记录崩溃日志的时间,我没有使用我的 phone!
所以我们猜测这是一次“假的”崩溃,记录了崩溃,但扩展程序并没有真正崩溃。
有人面临同样的问题吗? 谢谢!
回答我自己的问题,
@matt 是对的,现在我只在数据获取任务完成时才调用 completionHandler
,而不是总是在 widgetPerformUpdateWithCompletionHandler
方法的最后调用 completionHandler
。
我没有再收到崩溃,问题已解决!