ios中ios 0x8badf00dd表示是哪个地址

iOS Crash Log 分析(三)
打开Crash Log 会看到如下的信息:
Incident Identifier: AF4F2C83-8F68-47EF-B5AA-F16B067B5DF4
CrashReporter Key: f0f3cec086ed4b35b
Hardware Model: iPhone8,1
Process: kidneyUser [896]
Path: /private/var/containers/Bundle/Application/48C71AA1-EB99-49B1-ABD7-2903DBA8E394/kidneyUser.app/kidneyUser
Identifier: kidneyDiseaseHospitalUser
Version: 1 (1.0)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time:
10:45:43.43 +0800
Launch Time:
10:42:07.07 +0800
OS Version: iOS 9.3.1 (13E238)
Report Version: 105
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
Filtered syslog:
None found
Last Exception Backtrace:
0 CoreFoundation 0x181aeee38 __exceptionPreprocess + 124
1 libobjc.A.dylib 0x objc_exception_throw + 56
2 CoreData 0x18393ab44 -[NSManagedObjectModel initWithContentsOfURL:] + 856
3 kidneyUser 0x 0x + 1966552
4 kidneyUser 0x1002b82dc 0x + 1966812
5 kidneyUser 0x 0x + 1967776
6 kidneyUser 0x1002b87cc 0x + 1968076
7 kidneyUser 0xx + 1966116
8 UIKit 0x186cc9128 -[UIApplication _terminateWithStatus:] + 280
9 UIKit 0x186ee7f08 __102-[UIApplication _handleApplicationDeactivationWithScene:shouldForceExit:transitionContext:completion:]_block_invoke2017 + 796
10 UIKit 0x186eeafd8 _runAfterCACommitDeferredBlocks + 292
11 UIKit 0x186ef8990 _cleanUpAfterCAFlushAndRunDeferredBlocks + 92
12 UIKit 0x186c2a4a4 _afterCACommitHandler + 96
13 CoreFoundation 0x181aa47b0 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
14 CoreFoundation 0x181aa2554 __CFRunLoopDoObservers + 372
15 CoreFoundation 0x181aa2984 __CFRunLoopRun + 928
16 CoreFoundation 0x1819ccd10 CFRunLoopRunSpecific + 384
17 GraphicsServices 0x GSEventRunModal + 180
18 UIKit 0x186ca1f70 UIApplicationMain + 204
19 kidneyUser 0x 0x + 2028008
20 libdyld.dylib 0x start + 4
Global Trace Buffer (reverse chronological seconds):
2.434148 AppleJPEG 0xea88 [0x12e203600] Releasing session
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x811c __pthread_kill + 8
1 libsystem_pthread.dylib 0x4ef8 pthread_kill + 112
2 libsystem_c.dylib 0xf9dac abort + 140
3 libc++abi.dylib 0xd3f4 __cxa_bad_cast + 0
4 libc++abi.dylib 0x9e98 default_unexpected_handler() + 0
5 libobjc.A.dylib 0x4248 _objc_terminate() + 124
6 libc++abi.dylib 0x6f44 std::__terminate(void (*)()) + 16
7 libc++abi.dylib 0x6b10 __cxa_rethrow + 144
8 libobjc.A.dylib 0x4120 objc_exception_rethrow + 44
9 CoreFoundation 0xccdb8 CFRunLoopRunSpecific + 552
10 GraphicsServices 0xb4088 GSEventRunModal + 180
11 UIKit 0xca1f70 UIApplicationMain + 204
12 kidneyUser 0xc71e8 0x + 2028008
13 libdyld.dylib 0xa8b8 start + 4
以上就是Crash Log 文件的信息(设备的信息, crash信息,异常信息, 线程信息)
1. 设备信息
Incident Identifier: AF4F2C83-8F68-47EF-B5AA-F16B067B5DF4 // crash的ID
CrashReporter Key: f0f3cec086ed4b35b // crash 的设备ID
Hardware Model: iPhone8,1 // 手机的型号 (iPhone8,1代表iPhone6s 8,2 代表iPhone6s Plus)
Process: kidneyUser [896] // App的名称 (该App的进程ID)
Path: /private/var/containers/Bundle/Application/48C71AA1-EB99-49B1-ABD7-2903DBA8E394/kidneyUser.app/kidneyUser // APP 的位置 路径
Identifier: kidneyDiseaseHospitalUser // bundle ID
Version: 1 (1.0) // APP的版本号
Code Type: ARM-64 (Native) // app的应用架构
Parent Process: launchd [1]
Date/Time:
10:45:43.43 +0800 // crash发生的时间
Launch Time:
10:42:07.07 +0800 // 进入应用的时间
OS Version: iOS 9.3.1 (13E238) // iOS的版本
Report Version: 105
如果产品上线之后, 回收集大量的Crash Log日志文件, 可以对Crash文件里面的手机型号,版本号, 手机型号, iOS系统版本,进行分类, 可以获得更多的信息, 更好的解决bug甚至未知的bug具体原因, 做更好的测试
2.异常信息
Exception Type: EXC_CRASH (SIGABRT) // 异常的类型
Exception Codes: 0x0 // 异常出错的代码
Exception Note: EXC_CORPSE_NOTIFY // 异常通知
Triggered by Thread: 0 // 异常发生的线程(0代表主线程, 其他为主线程)
补充常见的Exception Codes代码类型
Exception Codes: 常见代码有以下几种
0x8badf00d错误码:Watchdog超时,意为&ate bad food&。
0xdeadfa11错误码:用户强制退出,意为&dead fall&。
0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。
0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。
0xc00010ff错误码:因为太烫了被干掉,意为&cool off&。
0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为&dead lock&
补充常见的Exception Type异常类型的信息:
1.EXC_BAD_ACCESS:此类型是最常见的crash, 通常用于访问了不该访问的内存导致的,一般 EXC_BAD_ACCESS后面的()还会带有补充信息
SIGSEGV: 通常由于重复释放对象导致, 一般在ARC以后很少见到
SIGABRT: 收到Abort信号退出, 通常Foundtion库中的容器为了保护状态正常会做一些检测, 例如插入nil到数据中等会遇到此类错误.
SEGV(Segmentation Violation): 代表无效内存地址, 比如空指针, 未初始化指针, 栈溢出等.
SIGBUS: 总栈错误, 与SIGSEGV不同的是, SIGSEGV访问的是无效的地址, 而SIGBUS访问的是有效的地址, 但是总栈访问异常(如地址对齐问题)
SIGILL: 尝试执行非法的指令, 可能不被识别或者没有权限
SIGFPE: 数学计算相关问题, 比如除零操作
SIGIPIPE: 管道另一端没有进程接手数据
2. EXC_BAD_INSTRUCTION:此类异常通常由于线程执行非法指令导致
3. EXC_ARITHMETIC:除零错误会抛出此类异常
Last Exception Backtrace: 最后异常回溯, 一般根据这个代码就能找到具体的crash问题
下面截取的是微信的crash blog
Thread 0 name: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0xff24 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0xad20 _pthread_cond_wait + 704
2 Foundation 0xf9fdf0 -[NSCondition waitUntilDate:] + 344
3 Foundation 0xf9ce34 -[NSConditionLock lockWhenCondition:beforeDate:] + 256
4 UIKit 0xdbc4 -[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] + 196
5 UIKit 0xc05878 -[UIKeyboardImpl setKeyboardInputMode:userInitiated:] + 112
6 UIKit 0xc0de44 -[UIKeyboardImpl recomputeActiveInputModesWithExtensions:] + 336
7 UIKit 0xe8f0 -[UIKeyboardImpl setDelegate:force:] + 2292
8 UIKit 0x7eb0 -[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:] + 1180
9 UIKit 0x79e4 -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] + 80
10 UIKit 0x9670 -[UIResponder becomeFirstResponder] + 600
11 UIKit 0x9a1c -[UIView(Hierarchy) becomeFirstResponder] + 148
12 UIKit 0x0b34 -[UITextField becomeFirstResponder] + 64
13 UIKit 0xb1fe4 -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setFirstResponderIfNecessary] + 256
14 UIKit 0xb1498 -
我们可以看到发生Crash的线程的Crash调用栈, 从上到下分别代表调用顺序, 最上面的一个表示抛出异常的位置, 一次往下可以看到API调用顺序, 上图的信息表明本次Crash出现在[NSCondition waitUntilDate:]这个方法中(后面加的数值 我猜应该是地址偏移量O(&_&)O) 大概可以找到crash的具体原因(某个文件中的某个方法), 这样问题就浮出水面了, 方便产品上线后版本迭代, 修改BUG.IOS开发工具大汇总(一) - CSDN博客
IOS开发工具大汇总(一)
1、crash分析工具
1.1 &lldb+汇编分析: 最原生也是最强大的工具
1.2 &Cycript: 参考文章:/ios-security-cycript-runtime-analysis/
2、日志分析工具
2.1 &mac机子上:&
& & & & & & & &a、 phoneview & & & & & & &&(mac版没有看到可以提取日志的地方,连root路径也没有)
& & & & & & & & b、在xcode中徽标键+shift+2
& & & & & & & &c、同步助手 & & & & & & & & & & & (mac版没有看到可以提取日志的地方,连root路径也没有)
日志分析过程
什么是崩溃日志,从哪里能得它?
iOS设备上的应用闪退时,操作系统会生成一个崩溃报告,也叫崩溃日志,保存在设备上。
崩溃日志上有很多有用的信息,包括应用是什么情况下闪退的。通常,上面有每个正在执行线程的完整堆栈跟踪信息,所以你能从中了解到闪退发生时各线程都在做什么,并分辨出闪退发生在哪个线程上。
有几种方法可以从设备上获取崩溃日志。
设备与电脑上的iTunes Store同步后,会将崩溃日志保存在电脑上。根据电脑操作系统的不同,崩溃日志将保存在以下位置:
~/Library/Logs/CrashReporter/MobileDevice/
Windows XP:
C:Documents and Settings&USERNAME&Application DataApple ComputerLogsCrashReporterMobileDevice&DEVICE_NAME&
Windows Vista or 7:
C:Users&USERNAME&AppDataRoamingApple ComputerLogsCrashReporterMobileDevice&DEVICE_NAME&
当用户抱怨闪退时,你可以要求他让设备与iTunes同步,并根据操作系统的不同,到上述位置把崩溃日志下载下来,然后通过电子邮件发送给你。
你必需尽量获取用户设备生成的所有崩溃日志。因为崩溃日志越多,就越容易诊断问题所在!
另外,如果你装了Xcode,也能很容易通过Xcode从你的设备上获得崩溃日志。将iOS设备连接到电脑上,然后打开Xcode。从菜单栏上选择&Window &菜单, 然后选择&Organizer&(快捷方式是
Shift-CMD-2).
在 Organizer 窗口上, 选中&Devices&标签栏. 在左侧的导航面板上,选中&Device
Logs, 如下图所示:
看看上图,左侧有好几个 Device Logs 菜单项.&LIBRARY&下面的Device Logs是你所有设备(曾经连接到Xcode的)的日志 。每个设备下面的
Device Logs 是对应设备的日志。
应用提交到App Store后,你也能从&&获取到用户的崩溃日志. 登录到 iTunes Connect 上, 选择&Manage Your Applications, 点击相应的应用,
点击应用图标下面的&View Details&按钮, 然后点击右栏Links部分的 &Crash
Reports&。
如果没有崩溃日志,试试点击Refresh&按钮刷新一下。如果你的应用还卖得不多,或者刚上架不久,iTunes Connect账号上也可能还没有任何崩溃日志。
如果iTunes Connect上有崩溃日志,你将看到如下图:
有时,尽管有用户报告闪退,你仍然看不到崩溃报告。这时,最好让用户直接把崩溃报告发送给你。
什么情况下会产生崩溃日志?
两种主要情况会产生崩溃日志:
应用违反操作系统规则。
应用中有Bug。
违反iOS规则包括在启动、恢复、挂起、退出时watchdog超时、用户强制退出和低内存终止。让我们详细了解一下吧。
Watchdog 超时机制
从iOS 4.x开始,退出应用时,应用不会立即终止,而是退到后台。
但是,如果你的应用响应不够快,操作系统有可能会终止你的应用,并产生一个崩溃日志。这些事件与下列UIApplicationDelegate方法相对应:
application:didFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationDidBecomeActive:
applicationWillTerminate:
上面所有这些方法,应用只有有限的时间去完成处理。如果花费时间太长,操作系统将终止应用。
注意:&如果你没有把需要花费时间比较长的操作(如网络访问)放在后台线程上就很容易发生这种情况。关于如果避免这种情况的信息,请参考我们的另外两篇教程:&&和&。
用户强制退出
iOS 4.x开始支持多任务。如果应用阻塞界面并停止响应, 用户可以通过在主屏幕上双击Home按钮来终止应用。此时,操作应用将生成一个崩溃日志。
注意:&双击Home按钮后,你将看到运行过的所有应用。那些应用不一定是正在运行,也不一定是被挂起。
通常,用户点击Home按钮时,应用将在后台保留约10分钟,然后操作系统自动将其终止。 所以双击Home按钮显示的应用列表只是表明那是一系列过去打开过的应用。删除那些应用的图标不会产生任何崩溃日志。
低内存终止
子类化UIViewController时,你或许已经注意到didReceiveMemoryWarning方法。
在前台运行的应用拥有访问和使用内存的最高优化级。然而,这并不意味着该应用能使用设备的所有可用内存 ——每个应用只能使用一部分可用内存。
当内存使用达到一定程度时,操作系统将发出一个&UIApplicationDidReceiveMemoryWarningNotification&通知。同时,调用&didReceiveMemoryWarning&方法。
此时,为了让应用继续正常运行,操作系统开始终止在后台的其他应用以释放一些内存。所有后台应用被终止后,如果你的应用还需要更多内存,操作系统会将你的应用也终止掉,并产生一个崩溃日志。而在这种情况下被终止的后台应用,不会产生崩溃日志。
注意:&根据&,
Xcode不会自动添加低内存日志。你必需手动获取日志。 然而,根据我的个人经验,使用 Xcode 4.5.2, 低内存日志也会自动导入,只是”Process”和”Type”属性都被标为Unknown(未知)。
另外,值得一提的是在极短时间内分配一大块内存将给系统内存带来巨大负担。这样,也会产生内存警告的通知。
应用中有Bug
如你所想,大多数闪退都是由于应用中有Bug,因此大多数崩溃日志的产生都是因为应用中的Bug。Bug的种类的有很多。
在本教程的后半部分,你将通过调试一个会产生崩溃日志的含有Bug的应用,学习如何找到问题所在并进行修复!
崩溃日志的实例
让我们看看一个崩溃日志的实例,以使你在处理一些实际问题之前心里有谱。
事不宜迟,见见你的新朋友吧:
// 1: 进程信息
Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F
CrashReporter Key:
5af867f6eec76afee451bf9ae5f31
Hardware Model:
Rage Masters [4155]
/var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters
Identifier:
Rage Masters
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:
// 3: 异常
Exception Type:
Exception Codes: 0xbadf00d
Highlighted Thread:
// 4: 线程回溯
Thread 0 name:
Dispatch queue: com.apple.main-thread
libsystem_kernel.dylib
0x327f2eb4 mach_msg_trap + 20
libsystem_kernel.dylib
0x327f3048 mach_msg + 36
CoreFoundation
0x36bd4040 __CFRunLoopServiceMachPort + 124
CoreFoundation
0x36bd2d9e __CFRunLoopRun + 878
CoreFoundation
0x36b45eb8 CFRunLoopRunSpecific + 352
CoreFoundation
0x36b45d44 CFRunLoopRunInMode + 100
0x32ac343e CFURLConnectionSendSynchronousRequest + 330
Foundation
0x346e69ba +[ sendSynchronousRequest:returningResponse:error:] + 242
Rage Masters
0x000d00 + 8262
libsystem_kernel.dylib
0x32803d98 __workq_kernreturn + 8
libsystem_c.dylib
0x3a987cf6 _pthread_workq_return + 14
libsystem_c.dylib
0x3a987a12 _pthread_wqthread + 362
libsystem_c.dylib
0x3a9878a0 start_wqthread + 4
// 5: 线程状态
Thread 0 crashed with ARM Thread State (32-bit):
r3: 0x39529fc8
r4: 0xffffffff
r5: 0x2fd7d301
r6: 0x2fd7d300
r7: 0x2fd7d9d0
r8: 0x2fd7d330
r9: 0x3adbf8a8
r10: 0x2fd7d308
sp: 0x2fd7d2ec
lr: 0x001bdb25
// 6: 二进制映像
Binary Images:
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//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
这报告看起来像天书。:) 我们分几部分来解读吧:
(1) 进程信息
第一部分是闪退进程的相关信息。
Incident Identifier是崩溃报告的唯一标识符。
CrashReporter Key&是与设备标识相对应的唯一键值。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter
Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上。
Hardware Model&标识设备类型。 如果很多崩溃日志都是来自相同的设备类型,说明应用只在某特定类型的设备上有问题。上面的日志里,崩溃日志产生的设备是iPhone
Process&是应用名称。中括号里面的数字是闪退时应用的进程ID。
接下来几行不言自明,无需赘述。
(2) 基本信息
这部分给出了一些基本信息,包括闪退发生的日期和时间,设备的iOS版本。如果有很多崩溃日志都来自iOS 6.0,说明问题只发生在iOS 6.0上。
在这部分,你可以看到闪退发生时抛出的异常类型。还能看到异常编码和抛出异常的线程。根据崩溃报告类型的不同,在这部分你还能看到一些另外的信息。
(4) 线程回溯
这部分提供应用中所有线程的回溯日志。&回溯是闪退发生时所有活动帧清单。它包含闪退发生时调用函数的清单。看下面这行日志:
0x34648e88
0x83000 + 8740
它包括四列:
帧编号—— 此处是2。
二进制库的名称 ——此处是 XYZLib.
调用方法的地址 ——此处是 0x34648e88.
第四列分为两个子列,一个基本地址和一个偏移量。此处是0×83000 + 8740, 第一个数字指向文件,第二个数字指向文件中的代码行。
(5) 线程状态
这部分是闪退时寄存器中的值。一般不需要这部分的信息,因为回溯部分的信息已经足够让你找出问题所在。
(6) 二进制映像
这部分列出了闪退时已经加载的二进制文件。
符号化Symbolication
第一次看到崩溃日志上的回溯时,你或许会觉得它没什么意义。我们习惯使用方法名和行数,而非像这样的神秘位置:
Rage Masters
0x0001625c
0x2a000 + 3003
将这些十六进制地址转化成方法名称和行数的过程称之为符号化。
从Xcode的Organizer窗口获取崩溃日志后过几秒钟,崩溃日志将被自动符号化。上面那行被符号化后的版本如下 :
Rage Masters
0x0001625c
-[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)
Xcode符号化崩溃日志时,需要访问与App Store上对应的应用二进制文件以及生成二进制文件时产生的&.dSYM&文件。必需完全匹配才行。否则,日志将无法被完全符号化。
所以,保留每个分发给用户的编译版本非常重要。提交应用前进行归档时,Xcode将保存应用的二进制文件。可以在Xcode Organizer的Archives标签栏下找到所有已归档的应用文件。
在发现崩溃日志时,如果有相匹配的.dSYM文件和应用二进制文件,Xcode会自动对崩溃日志进行符号化。如果你换到别的电脑或创建新的账户,务必将所有二进制文件移动到正确的位置,使Xcode能找到它们。
注意:&你必需同时保留应用二进制文件和.dSYM文件才能将崩溃日志完整符号化。每次提交到iTunes Connect的构建都必需归档。
.dSYM文件和二进制文件是特定绑定于每一次构建和后续构建的,即使来自相同的源代码文件,每一次构建也与其他构建不同,不能相互替换。
如果你使用Build 和 Archive 命令,这些文件会自动放在适当位置。 如果不是使用Build 和 Archive命令,放在Spotlight能够搜索到的位置(比如Home目录)即可。
低内存闪退
因为低内存崩溃日志与普通崩溃日志略有不同,所以本教程特别分开说明一下。:]
iOS设备检测到低内存时,虚拟内存系统发出通知请求应用释放内存。这些通知发送到所有正在运行的应用和进程,试图收回一些内存。
如果内存使用依然居高不下,系统将会终止后台线程以缓解内存压力。如果可用内存足够,应用将能够继续运行而不会产生崩溃报告。否则,应用将被iOS终止,并产生低内存崩溃报告。
低内存崩溃日志上没有应用线程的堆栈回溯。相反,上面显示的是以内存页数为单位的各进程内存使用量。(在撰写本文的时候,一个内存页的大小是4KB。)
被iOS因释放内存页终止的进程名称后面你会看到jettisoned&字样。如果看到它出现在你的应用名称后面,说明你的应用因使用太多内存而被终止了。
低内存崩溃日志看起来像这样:
Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F
CrashReporter Key:
5af867f6eec76afee451bf9ae5f31
OS Version:
iPhone OS 3.1.3 (7E18)
Date/Time:
2012-10-17 21:39:06.967 -0400
Free pages:
Wired pages:
Purgeable pages:
Largest process:
Rage Masters
Count resident pages
Rage Masters
9320 (jettisoned) (active)
mediaserverd
dataaccessd
CommCenter
SpringBoard
2158 (active)
accessoryd
mDNSResponder
当应用发生低内存闪退时,你必需看看应用中内存使用的方式,以及是如何处理低内存警告的。你可以使用Instruments工具中使用Allocations 和 Leaks来发现内存分配问题和内存泄漏问题。如果你不知道如何利用 Instruments 检查内存问题,可以看看&。
还有,别忘记虚拟内存! Instruments工具的Leaks 和 Allocations 不能跟踪显存使用情况。必需使用 VM Tracker 才能查看显存使用情况。
VM Tracker 默认是关闭的。打开Instrument,手动 选中Automatic Snapshotting&标志或者按下Snapshot
Now&按钮。
本教程后面将会学习如何研究低内存崩溃日志。
在研究真实闪退场景之前,还有一点需要重点介绍一下:就是那些有趣的异常编码 。
你可以在报告的异常部分——前面代码的第3部分找到异常编码。有些编码比较常见。
通常,异常编码以一些文字开头,紧接着是一个或多个十六进制值,此数值正是说明闪退根本性质的所在。 &从这些编码中,可以区分出闪退是因为程序错误、非法内存访问或者是其他原因。
下面是一些常见的异常编码:
0x8badf00d: 读做 “ate bad food”! (把数字换成字母,是不是很像 :p)该编码表示应用是因为发生watchdog超时而被iOS终止的。 &通常是应用花费太多时间而无法启动、终止或响应用系统事件。
0xbad22222: 该编码表示 VoIP 应用因为过于频繁重启而被终止。
0xdead10cc: 读做 “dead lock”!该代码表明应用因为在后台运行时占用系统资源,如通讯录数据库不释放而被终止 。
0xdeadfa11: 读做 “dead fall”! 该代码表示应用是被用户强制退出的。根据苹果文档, 强制退出发生在用户长按开关按钮直到出现 “滑动来关机”, 然后长按
Home按钮。强制退出将产生 包含0xdeadfa11 异常编码的崩溃日志, 因为大多数是强制退出是因为应用阻塞了界面。
注意:&在后台任务列表中关闭已挂起的应用不会产生崩溃日志。 一旦应用被挂起,它何时被终止都是合理的。所以不会产生崩溃日志。
大展身手的时候到了!
好了! 你已经学习了所有分析崩溃日志和修复错误的基础知识!
假设你刚进入Rage-O-Rage有限公司工作。该公司有一个在App Store上热销的应用,叫 Rage Masters。
你的老板安迪要你帮忙解决几个用户经常抱怨闪退问题。你的任务就是研究这些闪退,符号化用户提供的崩溃日志,查找问题所在,并修复之。
你可以从&下载应用的源代码。
注意: 如果你想自己重新生成崩溃报告,请遵照以下指引:
下载源码然后在Xcode中打开工程文件。
使用正确的provisioning profile连接到iOS设备。
从Xcode工具栏上选择iOS设备——不是模拟器作为target,然后构建应用。
当你在设备上到默认页面(应用的全屏图片)时,立即在Xcode上点击停止按钮。
关闭 Xcode。
在设备上直接打开应用。
测试场景,完成后连接设备到电脑上,通过Xcode获取崩溃日志。
场景 1: 糟糕的代码
一封来自用户的邮件: “大哥,你的应用就是一坨屎! 我将其下载到我自己的iPod Touch和iPhone上,还下载到我儿子的iPod Touch上。在所有的设备上,都是还没打开就闪退了……”
别一封来自用户的邮件说, “我下载了你们的应用,一打开就闪退。真悲催…”
另一封邮件说得更明确:”你们的应用不能运行。我把它下载到我和妻子的设备上。所有设备都是 一打开就闪退了…”
好吧,别灰心! 这些意见藏着什么玄机呢?让我们看看崩溃日志吧:
Incident Identifier: 85833DBA-3DF7-43EE-AF80-4E5C51091F42
CrashReporter Key:
5af867f6eec76afee451bf9ae5f31
Hardware Model:
Rage Masters [20067]
/var/mobile/Applications/B2121A89-3D1F-4E61-BB18-0F/Rage Masters.app/Rage Masters
Identifier:
Rage Masters
Code Type:
ARM (Native)
Parent Process:
launchd [1]
Date/Time:
2012-11-03 13:37:31.148 -0400
OS Version:
iOS 6.0 (10A403)
Report Version:
Exception Type:
Exception Codes: 0xbadf00d
Highlighted Thread:
Application Specific Information:
Soheil-Azarpour.Rage-Masters failed to launch in
Elapsed total CPU
(seconds): 8.030 (user 8.030,
0.000), 20% CPU
Elapsed application CPU
(seconds): 3.840, 10% CPU
Thread 0 name:
Dispatch queue: com.apple.main-thread
libsystem_kernel.dylib
0x327f2eb4 mach_msg_trap + 20
libsystem_kernel.dylib
0x327f3048 mach_msg + 36
CoreFoundation
0x36bd4040 __CFRunLoopServiceMachPort + 124
CoreFoundation
0x36bd2d9e __CFRunLoopRun + 878
CoreFoundation
0x36b45eb8 CFRunLoopRunSpecific + 352
CoreFoundation
0x36b45d44 CFRunLoopRunInMode + 100
0x32ac343e CFURLConnectionSendSynchronousRequest + 330
Foundation
0x346e69ba +[ sendSynchronousRequest:returningResponse:error:] + 242
Rage Masters
0x000ea1c4 -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:36)
0x37f30ad4 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 248
0x37f3065e -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1186
0x37f28846 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 694
0x37ed0c3c -[UIApplication handleEvent:withNewEvent:] + 1000
0x37ed06d0 -[UIApplication sendEvent:] + 68
0x37ed011e _UIApplicationHandleEvent + 6150
GraphicsServices
0x _PurpleEventCallback + 588
GraphicsServices
0x370831ce PurpleEventCallback + 30
CoreFoundation
0x36bd4170 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 32
CoreFoundation
0x36bd4112 __CFRunLoopDoSource1 + 134
CoreFoundation
0x36bd2f94 __CFRunLoopRun + 1380
CoreFoundation
0x36b45eb8 CFRunLoopRunSpecific + 352
CoreFoundation
0x36b45d44 CFRunLoopRunInMode + 100
0x37f27480 -[UIApplication _run] + 664
0x37f242fc UIApplicationMain + 1116
Rage Masters
0x000ea004 main (main.m:16)
libdyld.dylib
0x3b630b1c start + 0
发现问题了吗? 异常编码是0xbadf00d,还有后面的报告:
Application Specific Information:
Soheil-Azarpour.Rage-Masters failed to launch in
Elapsed total CPU
(seconds): 8.030 (user 8.030,
0.000), 20% CPU
Elapsed application CPU
(seconds): 3.840, 10% CPU
这说明应用在启动时就闪退了,iOS的watchdog机制终止了应用。帅! 找到问题了,但是为什会发生这样的事呢?
接着往下看日志。 从下向上读回溯日志。最底下的帧 (frame 25: libdyld.dylib)是最先调用的,然后是帧24, Rage Masters, main (main.m:16) ,依此类推。
跟应用源代码相关的帧是最重要的。忽略掉系统库和框架。下一个与代码相关的帧是:
Rage Masters
0x -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)
应用在执行RMAppDelegate (RMAppDelegate.m:35)类application:didFinishLaunchingWithOptions:&方法第35
行代码时闪退。打开Xcode看看那行代码:
*directoryData = [ sendSynchronousRequest:request returningResponse:nil error:nil];
就是它了! 同步调用web服务?! 在主线程上?! 在&application:didFinishLaunchingWithOptions: 方法上?!! 谁写的代码呀?!
Network calls on the main thread makes kittens sad.
不管如何,问题得你来修复了。这个调用必需异步进行,甚至更理想的情况是,在application:didFinishLaunchingWithOptions:返回YES之后的其他部分再执行Web服务。
在其他地方调用可能需要比较多的修改。当下,我们只要使应用不闪退就行。可以在日后再实现更好的设计。 将上面那行讨厌的代码(及其下面的三行代码)换成下面这个异步的版本吧:
[ sendAsynchronousRequest:request
queue:[ mainQueue]
completionHandler:^( *response,
*cacheDirectory = [[[ defaultManager] URLsForDirectory:NSUserDirectory inDomains:NSCachesDirectory] lastObject];
*filePath = [ URLWithString:kDirectoryFile relativeToURL:cacheDirectory];
[data writeToFile:[filePath absoluteString] atomically:YES];
场景 2: 无法响应事件的按钮
一名用户说: “我不能将某个rage master添加到书签里面。我想添加的时候应用就闪退…”
用一名用户说 :”书签不能用 … 在详细页面上,点击书签按钮,应用就闪退了!”
上面的抱怨说得不是很清楚,引起问题的原因肯定有多样。看看崩溃日志:
Incident Identifier: 3AAA63CC-3088-41CC-84D9-82FE03F9F354
CrashReporter Key:
5af867f6eec76afee451bf9ae5f31
Hardware Model:
Rage Masters [20090]
/var/mobile/Applications/B2121A89-3D1F-4E61-BB18-0F/Rage Masters.app/Rage Masters
Identifier:
Rage Masters
Code Type:
ARM (Native)
Parent Process:
launchd [1]
Date/Time:
2012-11-03 13:39:00.081 -0400
OS Version:
iOS 6.0 (10A403)
Report Version:
Exception Type:
EXC_CRASH (SIGABRT)
Exception Codes: 0x0
Crashed Thread:
Last Exception Backtrace:
CoreFoundation
0x36bff29e __exceptionPreprocess + 158
libobjc.A.dylib
0x34f0f97a objc_exception_throw + 26
CoreFoundation
0x36c02e02 -[() doesNotRecognizeSelector:] + 166
CoreFoundation
0x36c0152c ___forwarding___ + 388
CoreFoundation
0x36b58f64 _CF_forwarding_prep_0 + 20
0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68
0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26
0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40
0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498
0x37fbade4 -[UIControl touchesEnded:withEvent:] + 484
0x37ee35f4 -[UIWindow _sendTouchesForEvent:] + 520
0x37ed0804 -[UIApplication sendEvent:] + 376
0x37ed011e _UIApplicationHandleEvent + 6150
GraphicsServices
0x3708359e _PurpleEventCallback + 586
GraphicsServices
0x370831ce PurpleEventCallback + 30
CoreFoundation
0x36bd416e __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 30
CoreFoundation
0x36bd4112 __CFRunLoopDoSource1 + 134
CoreFoundation
0x36bd2f94 __CFRunLoopRun + 1380
CoreFoundation
0x36b45eb8 CFRunLoopRunSpecific + 352
CoreFoundation
0x36b45d44 CFRunLoopRunInMode + 100
GraphicsServices
0x GSEventRunModal + 70
0x37f242fc UIApplicationMain + 1116
Rage Masters
0x000ca004 main (main.m:16)
libdyld.dylib
0x3b630b1c start + 0
异常代码是SIGABRT。通常, &SIGABRT 异常是由于某个对象接收到未实现的消息引起的。 或者,用简单的话说,在某个对象上调用了不存在的方法。
这种情况一般不会发生,因为A对象调用了B方法,如果B方法不存在,编译器会报错。但是,如果你是使用selector间接调用方法的,编译器则无法检测对象是否存在该方法了。
回到崩溃日志。它指出闪退发生在编号为0的线程上。 这意味着很可能是在主线程上调用了某个对象没有实现的方法。
如果你接着阅读回溯日志,会发现跟你的代码相关的只有帧22, main.m:16. 这没有多大帮助。 :[
继续向上查看框架调用,出现这个:
CoreFoundation
0x36c02e02 -[() doesNotRecognizeSelector:] + 166
这不是你自己写的代码。但至少它确认了是对象调用了一个没有实现的方法。
回到RMDetailViewController.m文件, 因为那是书签按钮实现动作的地方。 找到书签功能代码:
-(IBAction)bookmarkButtonPressed {
self.master.isBookmarked = !self.master.isB
// Update shared bookmarks
if (self.master.isBookmarked)
[[RMBookmarks sharedBookmarks] bookmarkMaster:self.master];
[[RMBookmarks sharedBookmarks] unbookmarkMaster:self.master];
// Update UI
[self updateBookmarkImage];
看起来没什么问题,再检查一下storyboard (XIB文件) ,确认按钮连接的正确性。
就是它了! 在&MainStoryboard.storyboard,按钮连接的是 bookmarkButtonPressed: 而不是bookmarkButtonPressed
(注意后面的分号说明方法有一个参数)。 只要将上面的方法签名修改成这样就能修复问题了:
-(IBAction)bookmarkButtonPressed:(id)sender {
// Remain unchanged..
当然,你也可以简单地在XIB文件上删除错误的连接,然后重新连接方法,使XIB文件连接到正确的方法上。两者方法都行。
又处理了一个闪退问题,好样的。:]
场景 3: 表格上的Bug
另一用户抱怨道, “在书签视图上无法删除书签…” 还有另一用户抱怨同样的问题, “当我试图删除书签时,应用闪退…”
这些邮件没什么作用,还是看看崩溃日志!
Incident Identifier: 5B62D681-D8FE-41FE-8D52-AB7E6D6B2AC7
CrashReporter Key:
5af867f6eec76afee451bf9ae5f31
Hardware Model:
Rage Masters [20088]
/var/mobile/Applications/B2121A89-3D1F-4E61-BB18-0F/Rage Masters.app/Rage Masters
Identifier:
Rage Masters
Code Type:
ARM (Native)
Parent Process:
launchd [1]
Date/Time:
2012-11-03 13:38:45.762 -0400
OS Version:
iOS 6.0 (10A403)
Report Version:
Exception Type:
EXC_CRASH (SIGABRT)
Exception Codes: 0x0
Crashed Thread:
Last Exception Backtrace:
CoreFoundation
0x36bff29e __exceptionPreprocess + 158
libobjc.A.dylib
0x34f0f97a objc_exception_throw + 26
CoreFoundation
0x36bff158 +[ raise:format:arguments:] + 96
Foundation
0x346812aa -[ handleFailureInMethod:object:file:lineNumber:description:] + 86
0x37f04b7e -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 7690
0x -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 22
Rage Masters
0x000fd9ca -[RMBookmarksViewController tableView:commitEditingStyle:forRowAtIndexPath:] (RMBookmarksViewController.m:68)
0x -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 80
0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68
0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26
0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40
0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498
0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68
0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26
0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40
0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498
0x37fbade4 -[UIControl touchesEnded:withEvent:] + 484
0x37ee35f4 -[UIWindow _sendTouchesForEvent:] + 520
0x37ed0804 -[UIApplication sendEvent:] + 376
0x37ed011e _UIApplicationHandleEvent + 6150
GraphicsServices
0x3708359e _PurpleEventCallback + 586
GraphicsServices
0x370831ce PurpleEventCallback + 30
CoreFoundation
0x36bd416e __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 30
CoreFoundation
0x36bd4112 __CFRunLoopDoSource1 + 134
CoreFoundation
0x36bd2f94 __CFRunLoopRun + 1380
CoreFoundation
0x36b45eb8 CFRunLoopRunSpecific + 352
CoreFoundation
0x36b45d44 CFRunLoopRunInMode + 100
GraphicsServices
0x GSEventRunModal + 70
0x37f242fc UIApplicationMain + 1116
Rage Masters
0x000fb004 main (main.m:16)
libdyld.dylib
0x3b630b1c start + 0
这看起来跟前面那个崩溃日志很像。是另一个SIGABRT 异常。 你可能想知道是否是相同的问题:发送信息到一个没有实现相应方法的对象?
让我们从回溯日志看看哪些方法被调用了。从底部开始,你的源代码最后被调用的是帧 6:
Rage Masters
0x00088c66 -[RMBookmarksViewController tableView:commitEditingStyle:forRowAtIndexPath:] (RMBookmarksViewController.m:68)
这是UITableViewDataSource 的一个方法. 呵呵?! 毫无疑问苹果已经实现了该方法 —— 你可以重载它, 但不像是还没有实现。而且,这是个可选的委派方法。 所以问题不是调用了一个没有实现的方法。
再看看上面的几个帧:
Foundation
0x346812aa -[ handleFailureInMethod:object:file:lineNumber:description:] + 86
0x37f04b7e -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 7690
0x -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 22
帧 5, UITableView调用了它自己的另一个方法&deleteRowsAtIndexPaths:withRowAnimation:&然后是看起来像苹果内部方法的_endCellAnimationsWithContext:&被调用。然后Foundation
framework发生异常handleFailureInMethod:object:file:lineNumber:description:.
这些分析结合用户的抱怨,看起来是你在处理UITableView删除行过程中有Bug。回到Xcode。你知道看哪里吗 ? 能从崩溃日志中判断出来? 就是RMBookmarksViewController.m文件的第68行:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:( *)indexPath {
[self.tableView deleteRowsAtIndexPaths:[ arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
发现问题了吗? 给你点时间,仔细看一下。
找到了吧! 数据源呢? 代码在表格视图上删除了一行,但并没有修改背后的数据源。把上面的代码替换成下面的就能修复问题了:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:( *)indexPath {
RMMaster *masterToDelete = [bookmarks objectAtIndex:indexPath.row];
[bookmarks removeObject:masterToDelete];
[[RMBookmarks sharedBookmarks] unbookmarkMaster:masterToDelete];
[self.tableView deleteRowsAtIndexPaths:[ arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
搞定了!走起,讨厌的 bug!!
3、内存泄露检查工具
3.1Clang Static Ananlyzer
这些工具和技术在技术文章 TN2239, iOS Debugging Magic 中描述。更确切地说,是使用NSZombie 来发现 release 过多的对象。&
你还可以使用 Instruments 来跟踪引用计数事件,并寻找内存泄露。参看 Viewing and&Analyzing Trace Data.&
4、 iphone真机抓包工具
iFunbox v2.7
5、系统级查找问题工具
承了 UNIX 的优良传统,都是命令行工具,而且输出结果很容易被 grep(1)处理,因此这些工
具不仅适合手工使用,还适合在脚本中调用。&
5.1 &filemon
第 3 章介绍了一个名为“filemon”的工具,这个工具可以实时显示 OS X 和 iOS 上文件
系统的活动。这个工具的命名是为了向 Russinovich 的同名工具致敬。这个简单的工具基于
OS X 和 iOS 5 上的 FSEvents 设备,能够跟踪文件系统相关的事件,例如文件的创建和删除。&
第 4 章介绍了一个名为 psx 的工具,这是一个类似 ps 的增强版工具,可以显示 OS X 中
进程和线程的相关信息。这个工具在第 4 章中特别重要,该章讲解了进程的内部结构,并且
演示了一个没有文档的系统调用 proc_info。如果查看的是自己创建的线程,这个工具不需要
有特别的权限,但是查看其他进程则需要 root 权限。这个工具可以从本书的支持网站免费下
载,带有完整的源代码。&
5.3 & jtool&
对于大部分和二进制文件相关的功能,可以使用 OS X 自带的 otool(1),这个工具能够很
全面地分析数据区域(data section),而且由于 ARM 架构具有两种模式的汇编,所以显示 ARM
二进制文件的时候会让人感到混淆。jtool 的目标是增强 otool,不仅解决了 otool 的这些缺陷,
还提供了静态二进制分析的新特性。这个工具对第 4 章特别有用,该章详细分析了 Mach-O
文件格式,而且由于这个工具有很多有用的特性,例如寻找文件中的引用以及一些有限的反
汇编能力,所以在后面几章也挺有用。这个工具可以从本书的支持网站免费下载,但是是闭
5.4 & dEFI&
这个简单的程序可以导出 Intel Mac 上的固件(EFI)变量,还可以显示注册的 EFI提供商。
这个工具演示了基本的 EFI 编程技术——如何与引导服务和运行时服务进行接口。这个工具
可以免费下载,带有完整的源代码。第 6 章介绍这个工具。 深入解析 Mac OS X & iOS 操作系统&
5.5 &joker&
第 8 章介绍的 joker 工具是一个简单的工具,这个工具可以用来和内核交互(特别是在 iOS
上)。这个工具可以查找并显示 iOS 和 OS X内核的系统调用和 Mach 陷阱表,显示 sysctl 结
构,并且在二进制文件中查找特定的模式。这个工具非常适合于逆向工程和黑客一类的活动,
因为 Apple 已经不再导出陷阱和系统调用符号了。&
5.6 corerupt&
本书提供了 corerupt 工具。通过这个工具可以将任何进程的虚拟内存映射以核心转储兼容的
格式导出到一个文件,类似于 Windows 的 Create Dump File 功能,也很像 Mac OS X Internals:&
A Systems Approach 一书中使用的 gcore 工具。corerupt 在其前身的基础上有了增强,提供了
对 ARM 的支持,还支持对虚拟内存映射进行入侵式的操作,例如修改内存页面。&
5.7 & HFSleuth&
HFSleuth 是本书中的一个重要工具,这是一个用于查看 OS X 原生的文件系统 HFS+支撑
结构的多合一命令行工具。之所以开发这个工具,是因为确实没有什么其他方式能够展示这
个非常复杂的文件系统的内部工作原理。Singh 的书 Mac OS X Internals: A Systems Approach&
中也包含了一个类似的工具,称为 hfsdebug,这个工具的功能少一些,而且只支持 PowerPC,
后来被一个商业工具 fileXRay 所替代。&
为了在真实的文件系统上使用 HFSleuth,必须能够读这个文件系统。一种方法就是引导
这个文件系统。HFSleuth 的功能几乎都是只读的,所以可以保证这个工具非常安全。但是访
问文件系统所在的底层块设备(有时候是字符设备)的访问权限通常是 rw-r-----,意味着设备不
能被其他用户读访问。如果您通常情况下不信任 root,并且坚持要使用较低的权限(这是一个
明智的决定!),那么一个同等有效的替代方案是通过 chmod(1)修改 HFS+分区所在设备的权
限,使得自己的用户有权限读(通常使用 o+r 参数)。一些高级功能(例如修复和 HFS+/HFSX
转换)要求写访问权限。HFSleuth 可以从本书的支持网站免费下载,而且会一直免费。不过和
其前任一样,这个工具也不是开源的。&
5.8 & lsock&
netstat -o 是一个大家都非常需要的功能,能够显示进程对系统中 socket 的所有权,但是
这个功能在 OS X 中就没有了。在 OS X 中,这个功能要通过 lsof(1)实现,但是后者需要剔除
其他打开的文件将 socket 滤出来,所以比较麻烦。另一个缺失的功能是显示正在创建的 socket
连接,就像 Windows 的 TCPMon 提供的功能一样。第 17 章介绍的这个工具使用了一个没有
正式文档的内核控制协议 com.apple.network.statistics,这个协议可以获得 socket 创建时候的
实时通知。这个工具特别容易集成到脚本中,因此可以很方便地用作连接事件处理程序。&
5.9 & jkextstat&
使用的最后一个工具是 jkextstat,这是一个 kextstat(8)兼容的工具,能够列出内核
扩展。和最初的版本不一样,这个工具支持详细输出(verbose)模式,而且可以用于 iOS。因
此,这个工具对于 iOS 内核的探讨来说价值重大,而这件事在这本书出现之前是很困难的,
因为 iOS 的二进制 kextstat 使用了不再被支持的 API。这个工具在最初的版本上有了改进,
允许更详细的输出信息,能关注于特定的内核扩展,而且还支持输出到 XML格式。
插件和工具介绍内容均收集于网络,太多了就不一一注明了,在此谢过!
5.10、Charles
为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。Charles通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析。一个可查看所有HTTP和SSL/HTTPS流量的工具。这款工具对于你测试和服务器端进行交互的应用非常有用
5.11、xScope
xScope带有六种不同的工具,帮助每一个设计者快速、精确的完成工作,这些工具功能灵活、强大,包括∶量度距离和角度的标尺、不同大小画面的屏幕、放大镜、精确垂直和水平标记辅助线、精确阔度, 高度和原来排成直线标记框架、找寻画面上全符合位置的 交叉点。
5.12、 Flurry
1.免费。可以收集用户的分布信息,用户对不同功能的使用频率,用户手机上的具体功能的执行信息(比如某按钮响应的执行时间)。并提供一些分析并以图表的方式显示出来,比如执行时间分布区间直方图,平均执行时间等等。
2.需要在网页上查看数据分析,刷新时间很慢。比如在你的程序执行后大约2个小时以上才能在网页上显示出来(GoogleAnalytics更是要24h,Localytics快一些二十分钟)。分析项目是固定的。图表显示不能更改或者自定义。不能直接看到所有数据(只能通过图表看到分析过了的数据分布的大概信息)
3.如果一定要获取所有的具体数据信息,可以通过Flurry的API来通过输入指定的网址和参数来获取指定的数据(XML或JSON
5.13、Crashlytics,
Crashlytics是基于云的错误报告解决方案,旨在找到所有崩溃应用的共同点。
通过写一行简单的代码来激活一个大概75KB的SDK,然后在AmazonWeb Services的云上来运行错误报告,最后给出关于你的应用崩溃的一个简单的报告。这是目前对移动开发者最有用最简单的错误报告系统。
5.14、Base
一款Mac OS X app,可用来创建、设计、编辑以及浏览SQLite 3数据库文件。
5.15、Pony Debugger
PonyDebugger是一个很给力的iOS调试工具,它的监视器安装在Chrome浏览器下做为插件使用,通过监视器和PonyDebugger的iOSSDK相辅相成,可以很好的监视App的运作情况.它的突出的亮点功能如下:
1:实时的检测应用与网络的交互情况
2:查看应用内CoreData的数据变化
3:实时反馈UI层的层级情况
5.16、Cocoapods
CocoaPods是一个可以帮你集中管理第三方库的开源项目,运行在Ruby的环境下,基于GitHub托管优势,你可以很方便的查阅目前依赖于CocoaPods的资源.
并且,CocoaPods是可靠,稳定,安全的.可以为你在使用第三方库资源时节省大部分的配置和部署时间.更专心的专注于Coding!
5.17、Appledoc
做项目的人多了,就需要文档了。今天开始尝试写一些项目文档。appledoc是一个可以帮你生成Objective-C代码注释的辅助工具,appledoc所生成的注释API文档与苹果类库的API文档保持一致.
这可以让Xcode能够识别出我们自己的API文档.
5.18、Dash
一款api查询,必备。
5.19、DashXcodeplugin:一个添加了Dash支持的Xcode插件。当使用Option-Click(或者作用相同的键盘快捷键)查看选中符号的文档时,该工具允许你使用Dash代替Xcode自己的文档查看器。
5.20、Simpholders
SimPholders可让你快速直接地访问iPhone模拟器应用的app文档。你可以通过SimPholders找到数据库文件、永久存储以及缓存。说白了,就是你不用去找app文件夹了,直接点击界面,他就会把那个文件夹直接给你打开!
5.21、PaintCode
PaintCode是一款简单的矢量图形绘制工具,通过PaintCode,你可以直接在画布上画图,并且能够直接生成适用于iOS的Objective-C代码。说白了,就是你画一条线,下边直接给出你代码!
5.22、Liya
可视化操作Sqlite以及CoreData!
5.23、Briefs
设计师可以利用Briefs设计完整的iPhone、iPad应用交互模型,并利用模拟器即时体验设计的成果
5.24、Omnigraffle
非常快地制作你的iPhone应用的演示界面。
5.25、GlyphishIcons
你可能能从上面的这些图标中看到Flipboard 和 Twitter 在iOS上的应用使用了其中的一些图标。是的,这些个小图标对你的开发很有帮助。
分布式版本控制系统和管理系统,其优点是:快和简单易用。
5.27、XcodeColors:为应用调试输出添加有颜色的代码,从而简化调试,可与CocoaLumberjack一同使用。
5.28、ColorSense:一款Xcode插件,能让开发者更简单更视觉换地使用UIColor和NSColor。当光标位于UIColor实例上时,颜色将会出现在屏幕上。点击颜色则可打开颜色选择器。该插件的编辑菜单增加了一些项目来插入颜色或者暂时禁用颜色高亮。菜单没有默认的键盘快捷键,但你可以通过系统的键盘参数选择进行设置。
20、CocoaPodsXcodePlugin:一款Xcode插件,允许你直接从Xcode管理CocoaPod依赖。
21、XcodeSnippets:这视乎是最明显的一个,但却可以减少大量开发时间。创建起来像drag-and-drop那么简单,这里有很多优秀的示例(XcodeCodeSnippets、CodeSnippets )。
22、Kiwi:适用于iOS的TDD/BDD测试平台。Kiwi让单元测试更加易读,类似Ruby测试工具RSpec。(相关:TDD的iOS开发初步以及Kiwi使用入门 )
23、Specta:一个轻量级的Objective-C和Cocoa的TDD/BDD框架,类似Kiwi,有类似RSpec的语法。通常会结合Expecta框架一起使用。
24、Cedar:Kiwi和Specta都基于该框架,同样使用RSpec风格的语言。
上述Kiwi、Specta、Expecta以及Cedar都可以通过CocoaPods添加到你的项目中。
25、xctool:xctool是来自Facebook的优秀开发工具,可以让你通过命令行创建和测试你的应用。除了比苹果提供的xcodebuild工具好用外,它的输出可以注入CI软件,因此更具灵活性。
26、Jenkins:一个开源的持续集成服务器,配置简单。通过Xcode插件,你可以用Jenkins来测试、签名、创建以及分发应用。Jenkins非常人性化,ANSI彩色输出,这些都是额外的功能。
27、Xcodebots:该工具自动化了创建、分析以及测试应用的过程。使用了Mac OSXserver和苹果的指令。
28、HockeyApp ($) :类似TestFlight的服务,但也包含崩溃报告和用户反馈。
29、TestFlight:知名的iOS应用测试平台。2014年3月,苹果收购了该平台的开发商Burstly。TestFlight表示将会停止开发&&产品,并且目前的beta 测试 SDK 将不支持新顾客注册。目前的顾客仍然可以使用
TestFlight。
30、Mou:OS X上一款Markdown的编辑器。非常适用于编写自述文件、变更日志以及其他方面的内容。
31、HomeBrew:OS X上非常出色的包管理工具。
32、Alcatraz:开源的Xcode5包管理器,可以让你发现和安装插件、模板以及配色方案,无需手动复制文件。现已支持Xcode 5。
本文已收录于以下专栏:
相关文章推荐
本文首发于《程序员》杂志2014年6月刊,未经允许,请勿转载。
从苹果发明iPhone起,AppStore上的一个又一个类似flappy bird的一夜暴富的故事刺激...
iOS开发工具集(2)
KooFrank's
Den by koofrank  /  383d  //  keep unread  //  hide &...
本文首发于《程序员》杂志2014年6月刊,未经允许,请勿转载。
从苹果发明iPhone起,AppStore上的一个又一个类似flappy bird的一夜暴富的故事刺激...
xcode相关:
关于xcode 可设
偏好设置 command+,
清空缓存 可设
隐藏xcode command+h
隐藏其它 command+option+h
显示全部 可设
http://mobile.csdn.net/a/540.html
界面总不是一件很容易事,尤其是iPhone/iPad的界面,做过iOS开发的程序员,一...
Charles之协助iOS开发工具
那些好用的iOS开发工具
从苹果发明iPhone起,AppStore上的一个又一个类似flappy bird的一夜暴富的故事刺激着大量开发者加入移动开发大军。随着这些开发者出现的...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 ios 10进制转0x 的文章

 

随机推荐