[英]How do you implement global iPhone Exception Handling?
我的iPhone應用程序中有一次崩潰,它會拋出NSException。 崩潰報告在錯誤的位置和導致錯誤的位置上完全不明確。 有沒有一種聰明的方法讓我在某處設置頂級異常處理程序以查看導致它的原因? 我自己無法復制問題,但我的一些beta用戶當然可以。
什么是處理這種性質問題的聰明方法?
看起來你在這里問兩個問題:如何設置頂級異常處理程序; 以及如何處理確定根本原因的問題。
捕獲異常可以通過幾種不同的方式完成,但為此,最好的方法似乎是使用NSSetUncaughtExceptionHandler設置異常處理程序。
當您的應用程序引發異常時,它將由默認的異常處理程序處理。 此處理程序只會在應用程序關閉之前將消息記錄到控制台。 您可以使用上述功能設置自己的自定義異常處理程序來覆蓋它。 執行此操作的最佳位置是app delegate applicationDidFinishLaunching:方法。
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSSetUncaughtExceptionHandler(&myExceptionHandler);
}
設置自定義處理程序后,您將需要擴展默認輸出,以幫助您確定原因。
void myExceptionHandler(NSException *exception)
{
NSArray *stack = [exception callStackReturnAddresses];
NSLog(@"Stack trace: %@", stack);
}
不幸的是,與OSX相比,iPhone在產生良好的堆棧跟蹤方面似乎非常有限。 上面的代碼會產生一些看似垃圾的輸出; 但是,您可以通過atos工具運行此輸出,並且您應該能夠從中生成有用的堆棧跟蹤。
另一個選擇是遵循本文中的說明, 這將有助於自動生成一個很好的堆棧跟蹤。
由於這是針對beta測試人員的,您可能需要修補一下,讓它為您工作。
你說你自己無法復制問題,只能復制你的用戶。 在這種情況下,您可能會發現Apple的這份技術說明很有用:
https://developer.apple.com/library/content/technotes/tn2151/_index.html
更新 :雖然這篇文章仍然包含有用的信息,但它包含的一些鏈接是不可逆轉的。 建議使用此替代帖子中的信息。
如果您打算自己動手,可以使用其中一種方法
void onUncaughtException(NSException* exception)
{
//save exception details
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&onUncaughtException);
//Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
//Rest of the coding
}
void onUncaughtException(NSException* exception)
{
//Save exception details
}
int main(int argc, char *argv[])
{
@autoreleasepool {
NSSetUncaughtExceptionHandler(&onUncaughtException);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class]));
}
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
//Rest of the coding
}
int main(int argc, char *argv[])
{
@autoreleasepool {
@try {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class]));
}
@catch (NSException *exception) {
//Save the exception
}
@finally {
}
}
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
//Rest of the coding
}
在我的觀點中,不要嘗試在崩潰時將異常詳細信息發送到服務器,當他再次啟動應用程序時發送它。
如果您打算使用NSUserDefaults保存異常詳細信息,則必須在崩潰時同步它,否則它將不會持久存在。
以下代碼片段完成了這項工作。
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]synchronize];
}
在XCode中,應始終為objc_exception_throw
設置全局斷點。 然后你(通常)獲得一個更有意義的堆棧跟蹤,以了解實際嘗試拋出異常的內容。
你仍然可以在跟蹤中的任何地方獲得源自計時器代碼或其他地方的異常而沒有你自己的代碼,但是如果你看一下方法鏈,你通常可以弄清楚異常是什么(比如在目標中發送通知)離開了)。
跟蹤崩潰報告的另一個選項是Plausible CrashReporter ,這是一個開源代碼,可以自動從現場向您發送崩潰報告。
還有CrashReporterDemo ,這是另一個開源選項,它是Plausible CrashReporter和一些服務器代碼的組合,可以更好地跟蹤崩潰報告。
最后,有一個MacDevCrashReporter ,一個似乎與iOSExceptional.com有相似之處的服務,在另一個答案中提出。 我不知道他們的服務條款是什么,因為我沒有注冊測試版。 在進入太深之前絕對值得檢查。
看看Crittercism 。 它超出了您的要求,它允許您使用您的應用程序為所有用戶獲取此信息,因此您應該能夠看到自己的崩潰。
您還可以為您的特定版本上傳DYSM,它會自動在您的網站上為您表示崩潰。 這應該為您提供最清晰的堆棧跟蹤,而無需連接到調試器。
您可能還希望確保在Objetive-C異常中設置中斷。 在Xcode 4中,在breakpoints選項卡中,您可以添加一個斷點異常,該異常斷開C ++和Obj-C異常。 如果沒有這個,拋出異常的大多數堆棧跟蹤都是非常無益的。
祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.