崩潰日志詳解上

出處:http://www.iteye.com轉(zhuǎn)自? http://www.raywenderlich.com/zh-hans/30818/ios應(yīng)用崩潰日志揭秘?

?本文作者是? Soheil Moayedi Azarpour, 他是一名獨(dú)立iOS開發(fā)者。作為一名應(yīng)用開發(fā)者,你是否有過如下經(jīng)歷?Learn how to make sense of crash logs! 為確保你的應(yīng)用正確無誤,在將其提交到應(yīng)用商店之前,你必定進(jìn)行了大量的測(cè)試工作。它在你的設(shè)備上也運(yùn)行得很好,但是,上了應(yīng)用商店后,還是有用戶抱怨會(huì)閃退 ! 如果你跟我一樣是個(gè)完美主義者,你肯定想將應(yīng)用做到盡善盡美。于是你打開代碼準(zhǔn)備修復(fù)閃退的問題……但是,從何處著手呢? 這時(shí)iOS崩潰日志派上用場(chǎng)了。在大多數(shù)情況下,你能從中了解到關(guān)于閃退的詳盡、有用的信息。 通過本教程,你將學(xué)習(xí)到一些常見的崩潰日志案例,以及如何從開發(fā)設(shè)備和iTunes Connect上獲取崩潰日志文件。你還將學(xué)習(xí)到符號(hào)化( symbolication),從日志追蹤到代碼 。你還將學(xué)習(xí)調(diào)試一個(gè)在待定情況下會(huì)閃退的應(yīng)用。 讓我們開始動(dòng)手吧!什么是崩潰日志,從哪里能得它?iOS設(shè)備上的應(yīng)用閃退時(shí),操作系統(tǒng)會(huì)生成一個(gè)崩潰報(bào)告,也叫崩潰日志,保存在設(shè)備上。 崩潰日志上有很多有用的信息,包括應(yīng)用是什么情況下閃退的。通常,上面有每個(gè)正在執(zhí)行線程的完整堆棧跟蹤信息,所以你能從中了解到閃退發(fā)生時(shí)各線程都在做什么,并分辨出閃退發(fā)生在哪個(gè)線程上。 有幾種方法可以從設(shè)備上獲取崩潰日志。 設(shè)備與電腦上的iTunes Store同步后,會(huì)將崩潰日志保存在電腦上。根據(jù)電腦操作系統(tǒng)的不同,崩潰日志將保存在以下位置: Mac OS X: ~/Library/Logs/CrashReporter/MobileDevice/ Windows XP:? C:Documents and SettingsApplication DataApple ComputerLogsCrashReporterMobileDeviceWindows Vista or 7:C:UsersAppDataRoamingApple ComputerLogsCrashReporterMobileDevice當(dāng)用戶抱怨閃退時(shí),你可以要求他讓設(shè)備與iTunes同步,并根據(jù)操作系統(tǒng)的不同,到上述位置把崩潰日志下載下來,然后通過電子郵件發(fā)送給你。

你必需盡量獲取用戶設(shè)備生成的所有崩潰日志。因?yàn)楸罎⑷罩驹蕉?,就越容易診斷問題所在!

另外,如果你裝了Xcode,也能很容易通過Xcode從你的設(shè)備上獲得崩潰日志。將iOS設(shè)備連接到電腦上,然后打開Xcode。從菜單欄上選擇? Window? 菜單, 然后選擇? Organizer (快捷方式是 Shift-CMD-2).

在 Organizer 窗口上, 選中? Devices 標(biāo)簽欄. 在左側(cè)的導(dǎo)航面板上,選中? Device Logs, 如下圖所示:

Devices tab in Xcode Organizer

看看上圖,左側(cè)有好幾個(gè) Device Logs 菜單項(xiàng).? LIBRARY 下面的Device Logs是你所有設(shè)備(曾經(jīng)連接到Xcode的)的日志 。每個(gè)設(shè)備下面的 Device Logs 是對(duì)應(yīng)設(shè)備的日志。

應(yīng)用提交到App Store后,你也能從? iTunes Connect 獲取到用戶的崩潰日志. 登錄到 iTunes Connect 上, 選擇 Manage Your Applications, 點(diǎn)擊相應(yīng)的應(yīng)用, 點(diǎn)擊應(yīng)用圖標(biāo)下面的? View Details 按鈕, 然后點(diǎn)擊右欄Links部分的? Crash Reports 。

Crash Reports in iTunes Connect

如果沒有崩潰日志,試試點(diǎn)擊 Refresh 按鈕刷新一下。如果你的應(yīng)用還賣得不多,或者剛上架不久,iTunes Connect賬號(hào)上也可能還沒有任何崩潰日志。

如果iTunes Connect上有崩潰日志,你將看到如下圖:

Crash Reports in iTunes Connect

有時(shí),盡管有用戶報(bào)告閃退,你仍然看不到崩潰報(bào)告。這時(shí),最好讓用戶直接把崩潰報(bào)告發(fā)送給你。

什么情況下會(huì)產(chǎn)生崩潰日志?

兩種主要情況會(huì)產(chǎn)生崩潰日志:

應(yīng)用違反操作系統(tǒng)規(guī)則。

應(yīng)用中有Bug。

違反iOS規(guī)則包括在啟動(dòng)、恢復(fù)、掛起、退出時(shí)watchdog超時(shí)、用戶強(qiáng)制退出和低內(nèi)存終止。讓我們?cè)敿?xì)了解一下吧。

Watchdog 超時(shí)機(jī)制

從iOS 4.x開始,退出應(yīng)用時(shí),應(yīng)用不會(huì)立即終止,而是退到后臺(tái)。

但是,如果你的應(yīng)用響應(yīng)不夠快,操作系統(tǒng)有可能會(huì)終止你的應(yīng)用,并產(chǎn)生一個(gè)崩潰日志。這些事件與下列UIApplicationDelegate方法相對(duì)應(yīng):

application:didFinishLaunchingWithOptions:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationDidBecomeActive:

applicationWillTerminate:

上面所有這些方法,應(yīng)用只有有限的時(shí)間去完成處理。如果花費(fèi)時(shí)間太長(zhǎng),操作系統(tǒng)將終止應(yīng)用。

注意: 如果你沒有把需要花費(fèi)時(shí)間比較長(zhǎng)的操作(如網(wǎng)絡(luò)訪問)放在后臺(tái)線程上就很容易發(fā)生這種情況。關(guān)于如果避免這種情況的信息,請(qǐng)參考我們的另外兩篇教程:? Grand Central Dispatch 和? NSOperations。

用戶強(qiáng)制退出

iOS 4.x開始支持多任務(wù)。如果應(yīng)用阻塞界面并停止響應(yīng), 用戶可以通過在主屏幕上雙擊Home按鈕來終止應(yīng)用。此時(shí),操作應(yīng)用將生成一個(gè)崩潰日志。

注意: 雙擊Home按鈕后,你將看到運(yùn)行過的所有應(yīng)用。那些應(yīng)用不一定是正在運(yùn)行,也不一定是被掛起。

通常,用戶點(diǎn)擊Home按鈕時(shí),應(yīng)用將在后臺(tái)保留約10分鐘,然后操作系統(tǒng)自動(dòng)將其終止。 所以雙擊Home按鈕顯示的應(yīng)用列表只是表明那是一系列過去打開過的應(yīng)用。刪除那些應(yīng)用的圖標(biāo)不會(huì)產(chǎn)生任何崩潰日志。

低內(nèi)存終止

子類化UIViewController時(shí),你或許已經(jīng)注意到 didReceiveMemoryWarning方法。

在前臺(tái)運(yùn)行的應(yīng)用擁有訪問和使用內(nèi)存的最高優(yōu)化級(jí)。然而,這并不意味著該應(yīng)用能使用設(shè)備的所有可用內(nèi)存 ——每個(gè)應(yīng)用只能使用一部分可用內(nèi)存。

當(dāng)內(nèi)存使用達(dá)到一定程度時(shí),操作系統(tǒng)將發(fā)出一個(gè)? UIApplicationDidReceiveMemoryWarningNotification 通知。同時(shí),調(diào)用? didReceiveMemoryWarning 方法。

此時(shí),為了讓應(yīng)用繼續(xù)正常運(yùn)行,操作系統(tǒng)開始終止在后臺(tái)的其他應(yīng)用以釋放一些內(nèi)存。所有后臺(tái)應(yīng)用被終止后,如果你的應(yīng)用還需要更多內(nèi)存,操作系統(tǒng)會(huì)將你的應(yīng)用也終止掉,并產(chǎn)生一個(gè)崩潰日志。而在這種情況下被終止的后臺(tái)應(yīng)用,不會(huì)產(chǎn)生崩潰日志。

注意: 根據(jù)? 蘋果文檔, Xcode不會(huì)自動(dòng)添加低內(nèi)存日志。你必需手動(dòng)獲取日志。 然而,根據(jù)我的個(gè)人經(jīng)驗(yàn),使用 Xcode 4.5.2, 低內(nèi)存日志也會(huì)自動(dòng)導(dǎo)入,只是”Process”和”Type”屬性都被標(biāo)為Unknown(未知)。

另外,值得一提的是在極短時(shí)間內(nèi)分配一大塊內(nèi)存將給系統(tǒng)內(nèi)存帶來巨大負(fù)擔(dān)。這樣,也會(huì)產(chǎn)生內(nèi)存警告的通知。

應(yīng)用中有Bug

如你所想,大多數(shù)閃退都是由于應(yīng)用中有Bug,因此大多數(shù)崩潰日志的產(chǎn)生都是因?yàn)閼?yīng)用中的Bug。Bug的種類的有很多。

在本教程的后半部分,你將通過調(diào)試一個(gè)會(huì)產(chǎn)生崩潰日志的含有Bug的應(yīng)用,學(xué)習(xí)如何找到問題所在并進(jìn)行修復(fù)!

崩潰日志的實(shí)例

讓我們看看一個(gè)崩潰日志的實(shí)例,以使你在處理一些實(shí)際問題之前心里有譜。

事不宜遲,見見你的新朋友吧:

[objc]? view plain copy

// 1: 進(jìn)程信息

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:? 5a56599d836c4f867f6eec76afee451bf9ae5f31

Hardware Model:? ? ? iPhone4,1

Process:? ? ? ? Rage Masters [4155]

Path:? ? ? ? ? ? /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

Identifier:? ? ? Rage Masters

Version:? ? ? ? ??? (???)

Code Type:? ? ? ARM (Native)

Parent Process:? launchd [1]

// 2: 基本信息

Date/Time:? ? ? 2012-10-17 21:39:06.967 -0400

OS Version:? ? ? iOS 6.0 (10A403)

Report Version:? 104

// 3: 異常

Exception Type:? 00000020

Exception Codes: 0x000000008badf00d

Highlighted Thread:? 0

// 4: 線程回溯

Thread 0 name:? Dispatch queue: com.apple.main-thread

Thread 0:

0? libsystem_kernel.dylib? ? ? ? ? ? 0x327f2eb4 mach_msg_trap + 20

1? libsystem_kernel.dylib? ? ? ? ? ? 0x327f3048 mach_msg + 36

2? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36bd4040 __CFRunLoopServiceMachPort + 124

3? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36bd2d9e __CFRunLoopRun + 878

4? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36b45eb8 CFRunLoopRunSpecific + 352

5? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36b45d44 CFRunLoopRunInMode + 100

6? CFNetwork? ? ? ? ? ? ? ? ? ? ? ? 0x32ac343e CFURLConnectionSendSynchronousRequest + 330

7? Foundation? ? ? ? ? ? ? ? ? ? ? ? 0x346e69ba +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 242

8? Rage Masters? ? ? ? ? ? ? ? ? ? ? 0x000d4046 0xd2000 + 8262

Thread 1:

0? libsystem_kernel.dylib? ? ? ? ? ? 0x32803d98 __workq_kernreturn + 8

1? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a987cf6 _pthread_workq_return + 14

2? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a987a12 _pthread_wqthread + 362

3? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a9878a0 start_wqthread + 4

// 5: 線程狀態(tài)

Thread 0 crashed with ARM Thread State (32-bit):

r0: 0x00000000? ? r1: 0x00000000? ? ? r2: 0x00000001? ? ? r3: 0x39529fc8

r4: 0xffffffff? ? r5: 0x2fd7d301? ? ? r6: 0x2fd7d300? ? ? r7: 0x2fd7d9d0

r8: 0x2fd7d330? ? r9: 0x3adbf8a8? ? r10: 0x2fd7d308? ? r11: 0x00000032

ip: 0x00000025? ? sp: 0x2fd7d2ec? ? ? lr: 0x001bdb25? ? ? pc: 0x30301838

cpsr: 0x00000010

// 6: 二進(jìn)制映像

Binary Images:

0xd2000 -? ? 0xd7fff +Rage Masters armv7? /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

0x2fe41000 - 0x2fe61fff? dyld armv7? /usr/lib/dyld

0x327f2000 - 0x32808fff? libsystem_kernel.dylib armv7? /usr/lib/system/libsystem_kernel.dylib

0x328a8000 - 0x328bdfff? libresolv.9.dylib armv7? /usr/lib/libresolv.9.dylib

0x32a70000 - 0x32b35fff? CFNetwork armv7? /System/Library/Frameworks/CFNetwork.framework/CFNetwork

0x32b7a000 - 0x32cc3fff? libicucore.A.dylib armv7? /usr/lib/libicucore.A.dylib

0x32cc4000 - 0x32cc5fff? CoreSurface armv7? /System/Library/PrivateFrameworks/CoreSurface.framework/CoreSurface

0x32f65000 - 0x32f8afff? OpenCL armv7? /System/Library/PrivateFrameworks/OpenCL.framework/OpenCL

這報(bào)告看起來像天書。:) 我們分幾部分來解讀吧:

(1) 進(jìn)程信息

第一部分是閃退進(jìn)程的相關(guān)信息。

Incident Identifier是崩潰報(bào)告的唯一標(biāo)識(shí)符。

CrashReporter Key 是與設(shè)備標(biāo)識(shí)相對(duì)應(yīng)的唯一鍵值。雖然它不是真正的設(shè)備標(biāo)識(shí)符,但也是一個(gè)非常有用的情報(bào):如果你看到100個(gè)崩潰日志的CrashReporter Key值都是相同的,或者只有少數(shù)幾個(gè)不同的CrashReport值,說明這不是一個(gè)普遍的問題,只發(fā)生在一個(gè)或少數(shù)幾個(gè)設(shè)備上。

Hardware Model 標(biāo)識(shí)設(shè)備類型。 如果很多崩潰日志都是來自相同的設(shè)備類型,說明應(yīng)用只在某特定類型的設(shè)備上有問題。上面的日志里,崩潰日志產(chǎn)生的設(shè)備是iPhone 4s。

Process 是應(yīng)用名稱。中括號(hào)里面的數(shù)字是閃退時(shí)應(yīng)用的進(jìn)程ID。

接下來幾行不言自明,無需贅述。

(2) 基本信息

這部分給出了一些基本信息,包括閃退發(fā)生的日期和時(shí)間,設(shè)備的iOS版本。如果有很多崩潰日志都來自iOS 6.0,說明問題只發(fā)生在iOS 6.0上。

(3) 異常

在這部分,你可以看到閃退發(fā)生時(shí)拋出的異常類型。還能看到異常編碼和拋出異常的線程。根據(jù)崩潰報(bào)告類型的不同,在這部分你還能看到一些另外的信息。

(4) 線程回溯

這部分提供應(yīng)用中所有線程的回溯日志。 回溯是閃退發(fā)生時(shí)所有活動(dòng)幀清單。它包含閃退發(fā)生時(shí)調(diào)用函數(shù)的清單??聪旅孢@行日志:

2? ? XYZLib? ? 0x34648e88? ? 0x83000 + 8740

它包括四列:

幀編號(hào)—— 此處是2。

二進(jìn)制庫的名稱 ——此處是 XYZLib.

調(diào)用方法的地址 ——此處是 0x34648e88.

第四列分為兩個(gè)子列,一個(gè)基本地址和一個(gè)偏移量。此處是0×83000 + 8740, 第一個(gè)數(shù)字指向文件,第二個(gè)數(shù)字指向文件中的代碼行。

(5) 線程狀態(tài)

這部分是閃退時(shí)寄存器中的值。一般不需要這部分的信息,因?yàn)榛厮莶糠值男畔⒁呀?jīng)足夠讓你找出問題所在。

(6) 二進(jìn)制映像

這部分列出了閃退時(shí)已經(jīng)加載的二進(jìn)制文件。

符號(hào)化Symbolication

第一次看到崩潰日志上的回溯時(shí),你或許會(huì)覺得它沒什么意義。我們習(xí)慣使用方法名和行數(shù),而非像這樣的神秘位置:

6? ? Rage Masters? ? 0x0001625c? ? 0x2a000 + 3003

將這些十六進(jìn)制地址轉(zhuǎn)化成方法名稱和行數(shù)的過程稱之為符號(hào)化。

從Xcode的Organizer窗口獲取崩潰日志后過幾秒鐘,崩潰日志將被自動(dòng)符號(hào)化。上面那行被符號(hào)化后的版本如下 :

6? ? Rage Masters? ? 0x0001625c? ? -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)

Xcode符號(hào)化崩潰日志時(shí),需要訪問與App Store上對(duì)應(yīng)的應(yīng)用二進(jìn)制文件以及生成二進(jìn)制文件時(shí)產(chǎn)生的? .dSYM 文件。必需完全匹配才行。否則,日志將無法被完全符號(hào)化。

所以,保留每個(gè)分發(fā)給用戶的編譯版本非常重要。提交應(yīng)用前進(jìn)行歸檔時(shí),Xcode將保存應(yīng)用的二進(jìn)制文件??梢栽赬code Organizer的Archives標(biāo)簽欄下找到所有已歸檔的應(yīng)用文件。

在發(fā)現(xiàn)崩潰日志時(shí),如果有相匹配的.dSYM文件和應(yīng)用二進(jìn)制文件,Xcode會(huì)自動(dòng)對(duì)崩潰日志進(jìn)行符號(hào)化。如果你換到別的電腦或創(chuàng)建新的賬戶,務(wù)必將所有二進(jìn)制文件移動(dòng)到正確的位置,使Xcode能找到它們。

注意: 你必需同時(shí)保留應(yīng)用二進(jìn)制文件和.dSYM文件才能將崩潰日志完整符號(hào)化。每次提交到iTunes Connect的構(gòu)建都必需歸檔。

.dSYM文件和二進(jìn)制文件是特定綁定于每一次構(gòu)建和后續(xù)構(gòu)建的,即使來自相同的源代碼文件,每一次構(gòu)建也與其他構(gòu)建不同,不能相互替換。

如果你使用Build 和 Archive 命令,這些文件會(huì)自動(dòng)放在適當(dāng)位置。 如果不是使用Build 和 Archive命令,放在Spotlight能夠搜索到的位置(比如Home目錄)即可。

低內(nèi)存閃退

因?yàn)榈蛢?nèi)存崩潰日志與普通崩潰日志略有不同,所以本教程特別分開說明一下。:]

iOS設(shè)備檢測(cè)到低內(nèi)存時(shí),虛擬內(nèi)存系統(tǒng)發(fā)出通知請(qǐng)求應(yīng)用釋放內(nèi)存。這些通知發(fā)送到所有正在運(yùn)行的應(yīng)用和進(jìn)程,試圖收回一些內(nèi)存。

如果內(nèi)存使用依然居高不下,系統(tǒng)將會(huì)終止后臺(tái)線程以緩解內(nèi)存壓力。如果可用內(nèi)存足夠,應(yīng)用將能夠繼續(xù)運(yùn)行而不會(huì)產(chǎn)生崩潰報(bào)告。否則,應(yīng)用將被iOS終止,并產(chǎn)生低內(nèi)存崩潰報(bào)告。

低內(nèi)存崩潰日志上沒有應(yīng)用線程的堆?;厮?。相反,上面顯示的是以內(nèi)存頁數(shù)為單位的各進(jìn)程內(nèi)存使用量。(在撰寫本文的時(shí)候,一個(gè)內(nèi)存頁的大小是4KB。)

被iOS因釋放內(nèi)存頁終止的進(jìn)程名稱后面你會(huì)看到 jettisoned 字樣。如果看到它出現(xiàn)在你的應(yīng)用名稱后面,說明你的應(yīng)用因使用太多內(nèi)存而被終止了。

低內(nèi)存崩潰日志看起來像這樣:

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:? 5a56599d836c4f867f6eec76afee451bf9ae5f31

OS Version:? ? ? ? ? iPhone OS 3.1.3 (7E18)

Date/Time:? ? ? ? ? 2012-10-17 21:39:06.967 -0400

Free pages:? ? ? ? 96

Wired pages:? ? ? 10558

Purgeable pages:? 0

Largest process:? Rage Masters

Processes

Name? ? ? ? ? ? ? ? UUID? ? ? ? ? ? ? ? ? ? Count resident pages

Rage Masters? ? 9320 (jettisoned) (active)

mediaserverd? ? ? 255

dataaccessd? ? ? 505

syslogd? ? ? 71

apsd? ? ? 171

securityd? ? ? 243

notifyd? ? 2027

CommCenter? ? ? 189

SpringBoard? ? 2158 (active)

accessoryd? ? ? 91

configd? ? ? 371

fairplayd? ? ? 93

mDNSResponder? ? ? 292

lockdownd? ? 1204

launchd? ? ? 72

當(dāng)應(yīng)用發(fā)生低內(nèi)存閃退時(shí),你必需看看應(yīng)用中內(nèi)存使用的方式,以及是如何處理低內(nèi)存警告的。你可以使用Instruments工具中使用Allocations 和 Leaks來發(fā)現(xiàn)內(nèi)存分配問題和內(nèi)存泄漏問題。如果你不知道如何利用 Instruments 檢查內(nèi)存問題,可以看看 這個(gè)教程 。

還有,別忘記虛擬內(nèi)存! Instruments工具的Leaks 和 Allocations 不能跟蹤顯存使用情況。必需使用 VM Tracker 才能查看顯存使用情況。

VM Tracker 默認(rèn)是關(guān)閉的。打開Instrument,手動(dòng) 選中 Automatic Snapshotting 標(biāo)志或者按下 Snapshot Now 按鈕。

本教程后面將會(huì)學(xué)習(xí)如何研究低內(nèi)存崩潰日志。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自http://www.raywenderlich.com/zh-hans/30818/ios應(yīng)用崩潰日志揭秘 ...
    RunSnails閱讀 4,635評(píng)論 2 22
  • 異常編碼 在研究真實(shí)閃退場(chǎng)景之前,還有一點(diǎn)需要重點(diǎn)介紹一下:就是那些有趣的異常編碼 。 你可以在報(bào)告的異常部分——...
    中二修行者閱讀 2,057評(píng)論 0 3
  • 作為一名應(yīng)用開發(fā)者,你是否有過如下經(jīng)歷?經(jīng)常被領(lǐng)導(dǎo)叫去,讓看哪位哪位客戶運(yùn)行APP又崩潰了,感覺解決;天天被產(chǎn)品狗...
    繼續(xù)向前沖閱讀 2,995評(píng)論 0 9
  • 作為一名應(yīng)用開發(fā)者,你是否有過如下經(jīng)歷? 為確保你的應(yīng)用正確無誤,在將其提交到應(yīng)用商店之前,你必定進(jìn)行了大量的測(cè)試...
    姚姚先生閱讀 704評(píng)論 0 1
  • 轉(zhuǎn)自:http://www.cocoachina.com/industry/20130725/6677.html ...
    mandygao閱讀 700評(píng)論 0 4

友情鏈接更多精彩內(nèi)容