两个小时解决掉3个 BAD_ACCESS 的收获

首先,我说的是 iOS 开发,不是 Mac OS。

其次,这次解决的三个 BAD_ACCESS 都是由于 iOS 程序在收到 Memory Warning 后,非当前 UIViewController 执行 viewDidUnload 后出现的问题。

这类崩溃在真机上比较难测,因为是随机出现的,而且看 Crash Log 经常会看不出是哪行代码 BAD_ACCESS 了。所以这就需要善用模拟器提供的 “Hardware -> Simulate Memory Warning” 功能了。

同时为了能够方便的 Debug 出僵尸指针是谁,我在 Xcode 里加入以下三个环境变量:

NSZombieEnabled NSAutoreleaseFreedObjectCheckEnabled NSDebugEnabled

Xcode 4 的话编辑一下 Scheme,加到 Environment Variables 里即可(如果以前没加过的话)。

做完准备工作就能比较方便的进行 Debug 了。可以每切换一次 UIViewController 就模拟一次内存警告,看会不会崩溃。

接下来说说我这次遇到的三个问题。
1、一个低级错误

由于我们有时会几个人同时改一个文件,结果就发生了A用完一个实例以后顺手给释放掉了,但是却把B写在 viewDidUnload 里的代码给留下了。自然也就过度释放了。

这类过度释放的错误比较容易发现,只要改代码的时候稍微在原有文件里做一下搜索就能避免。

2、关于 Interface Builder 里的实例生命周期有多长的问题。

开发过 Mac OS 应用的同学都知道在开发 Mac 应用的时候,IB 里的实例 IBOutlet 到代码里是不用 retain 的。但是在 iOS 里却是要 retain 的。

这有什么区别呢?

如果你用的是 UIView 的话,的确,在 iOS 里不做 retain 也不要紧。因为 UIViewController 里的 UIView 本质上都是被 addSubview 到别的 UIView(UIWindow)里去的。但如果你在 IB 里放的是一个 NSObject,问题就出来了。

这也就是我遇到的问题。iOS 会把这个 NSObject 释放掉!

找这个问题花了我不少功夫,因为这个 NSObject 我只是在 IB 里连了连线,压根儿就没在代码里出现……解决方法其实很简单,在代码里加上

@property (nonatomic, retain) NSObject *someObject;

就好了(注意内存释放)。

3、BCTabBarController 带来的噩梦

在解决了以上问题后,整个程序仍然在满世界地不停的崩溃。这让我也很崩溃。咱好歹也算对 iOS 内存管理略有心得,搞个程序崩成这样实在是说不过去。

继续找下去发现问题出在一个第三方的开源控件:BCTabBarController 上。

用一个水准不高的第三方控件的结果就是给开发带来一定方便的同时,也带来了更多的麻烦(我不是在指责 BCTabBarController 的水准,因为要在苹果有限的公开 API 上完全自己来模拟原生 UITabBarController 的行为,的确是有难度的)。

这次的问题出在 BC 调用其管理的 UIViewController 的 viewWillAppear: 函数时,忽略了该 UIViewController 可能已经 viewDidUnload 过了。一上来就直接调用 viewWillAppear: ,结果当然不是崩掉就是逻辑乱掉。

解决方法是在 BC 调用 [viewController viewWillAppear:NO]; 之前加一句 [viewController view]; ,确保 viewDidLoad 先于 viewWillAppear: 被调用即可。

注:loadView 和 viewDidLoad 都不应该自己直接去调用,用 [viewController view]; 这种方法来让 view 自行载入的好处是,如果 view 已经被载入了,这一步操作不会让所有 view 再被载入一次。

现已发现的问题就是这么多,要在 iOS 上写个没有内存泄露又不会崩溃的程序实在是有难度。

千里单骑走关西

Note:由于照片是 Adobe RGB 色彩空间的,请用 Safari、FireFox 或 IE9 来看,用 Chrome 或者 IE8 看到的颜色可能会有点发灰。

在朦胧的春雨中行进

solo travel

 

山间的云雾让沿途风景变得格外清新
solo travel

 

神社里过着幸福生活的野猫
solo travel

 

金鸡独立?
solo travel

 

这难道就是松果的小时候?
solo travel

 

丹后半岛,天桥立,一道神奇的陆地把海洋一切为二
solo travel

 

在山顶赏花的好处是背景是大地而不是天空
solo travel

 

坐缆车下山途中,花,海湾
solo travel

 

冷冷的山,暖暖的洞
solo travel

 

公路在田间向远方延升,清晨的阳光透过薄雾给大地带来一丝温暖
solo travel

 

位于鸟取县的大沙丘
solo travel

 

沙丘中间的一弯清水,不知是不是海水?
solo travel

 

巨大的沙丘一直延伸入海。沙丘,沙滩,沙沙分不清楚
solo travel

 

这让我想起语文课上老渠的教导:大自然啊,真他妈大。人类啊,真他妈渺小。
solo travel

 

纵横的足迹。沙子的好处是,让你能很轻易的留下你来过的印迹。
solo travel

 

但是你能分清哪个才是你自己的足印吗?
solo travel

 

这一望无际的不是海,是湖。
solo travel

 

路边的休息站也搞得如此诗情画意
solo travel

 

原来这个无人问津的山间休息站也有自己的故事
solo travel

 

咱们管这个叫牌楼,日本人管这个叫鸟居
solo travel

 

许愿的纸条。我比较好奇下雨难道不会湿掉然后烂成一团吗?
solo travel

 

俩日
solo travel

 

深藏在底下的博物馆
solo travel

 

当年被火山熔岩活埋的树们
solo travel

 

神奇就神奇在没有被火山熔岩烧掉
solo travel

 

足足三四层楼高都被活埋了
solo travel

 

当年的树根,现如今已经是10几米深的地下了
solo travel

 

共生现象,一共有三个年轮。传说中的 3T
solo travel

 

广岛西南有一岛,名曰宫岛。其上住民与世隔绝,岛上群鹿与人为伴,相处甚是融洽。
solo travel

 

这个宫岛才应该叫鹿儿岛嘛!
solo travel

 

他们才是这个岛的主人
solo travel

 

原来不光山羊爱吃纸,鹿也爱!
solo travel

 

用 DS 拍照是很蛋疼的。
solo travel

 

岛上的渔民还是以前那套装扮
solo travel

 

漫步在海上
solo travel

 

为什么寺庙总能把好地方的山头给占了呢?
solo travel

 

有些硬币卡在这里已经很多年了
solo travel

 

好粗
solo travel

 

海水退去以后的宁静水塘
solo travel

 

广岛城
solo travel

 

姬路城下的日本园林
solo travel

 

虽然缺少江南园林的灵秀,但日本园林的精美还是体现得淋漓尽致
solo travel

 

红叶是绿色的园林中很好的点缀
solo travel

 

不太会认花,似乎是牡丹?
solo travel

 

红牡丹?
solo travel

 

被蛛丝挂在空中的一朵小花
solo travel

 

蜿蜒的石头小路,走在上面会发出沙沙的声响
solo travel

 

修缮中的国宝姬路城,世界文化遗产
solo travel

 

据说古代将军的阴灵会附着在上面
solo travel

 

不知道这个叫什么,姬路城上的图腾?
solo travel

 

世界遗产在修缮的好处是能够站在平时不可能的角度看房顶
solo travel

 

第七层的外观
solo travel

 

多达七层的城墙,盖个房子真不容易
solo travel

 

姬路城历代城主的家族徽章
solo travel

 

一个巨大的罩子把白鹭大天守整个罩在了里面,为的是不让纵横的脚手架破坏整个景观的感觉
solo travel

 

当年姬路里的姬就是这样消磨时间的
solo travel

 

光速回家
solo travel

Use Chrome or Safari to Debug your Node.js codes

1. Install node-inspector

npm install node-inspector

2. Start up node-inspector

node-inspector

>visit http://0.0.0.0:8080/debug?port=5858 to start debugging

3. Start up node

node –debug test.js

>debugger listening on port 5858 >Server running at http://127.0.0.1:8124/

4. Open URL: http://127.0.0.1:8080/debug?port=5858 in Chrome or Safari, Open Inspector in your browser, select the test.js file

5. Add a breakpoint in the test.js file

6. Open URL: http://127.0.0.1:8124/

You should see what you want.

test.js file:

var http = require('http');

var x = 0;
http.createServer(function (req, res) {
  x += 1;
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World ' + x);
}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');

 

HOW TO: Use newer Git in bash instead of the old one installed by Xcode 4 ?

Xcode 4 (since 4.0.2) will install git v1.7.3.4 into “/usr/bin/” by default.

You can use it in both Xcode and bash.

But what if you want to use a new version of git in bash (Xcode 4 will still using v1.7.3.4)? It’s easy to do so.

Step1: Download and install the new version from here: http://code.google.com/p/git-osx-installer/downloads/list

Step2: Edit your “~/.bash_profile” file (create one if doesn’t exist) and add a new line:

export PATH=/usr/local/git/bin:$PATH

Step3: Restart the bash

That’s all.