随想

当你坚持着自己的想法在做一件自己想做事情的时候,当你坚持着自己的原则拒绝去做一些事情的时候,总会有一些声音有意无意地告诉你:你这个傻逼,这个社会就是这样。

这个社会太浮躁了现在,巨大的通胀让每个人都想着去赚快钱,大家都很难静下心来做一件让自己开心的事情。嗯,让自己开心的事情。

Tim O’Reilly:

Money is like gasoline during a road trip. You don’t want to run out of gas on your trip, but you’re not doing a tour of gas stations. You have to pay attention to money, but it shouldn’t be about the money.

UITaleView 多选

效果就是 cell.contentView 右移,左侧留一空圆,点击选中,再点取消选中。

[_rootTable setEditing:YES animated:YES]; 进入多选,然后实现 delegate:

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
	// 关键所在
    return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView.editing) {
        if (_dataArray && [_dataArray count]>indexPath.row) {
            NSDictionary *dict = [_dataArray objectAtIndex:indexPath.row];
            [_pickedArray addObject:dict];
        }
    }
}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView.editing) {
        if (_dataArray && [_dataArray count]>indexPath.row) {
            NSDictionary *dict = [_dataArray objectAtIndex:indexPath.row];
            [_pickedArray removeObject:dict];
        }
    }
}

Preview and Copy text from QuickLook

  1. Enable QuickLook for all plain text file with QLStephen
  2. Open Terminal and run following code:

    defaults write com.apple.finder QLEnableTextSelection -bool true; killall Finder

  3. Done.

via 1, 2

iPad OS version history

iPad 的系统版本历史 (via iOS version history):

  1. 3.2/3.2.1/3.2.2,iPad Only.
  2. 4.2/4.2.1
  3. 4.3.x
  4. 5.x
  5. 6.x

iPad 的系统版本并不是连续的,3.2 是上市时的版本,iPad 独享。iOS 里程碑 4.0 刚开始并不支持 iPad,直到 4.2 才支持。4.3 随 iPad 2 发布,之后的 iOS 都是全设备支持。

所以做 iPad App 时系统要求可以从 4.2 起步,为了兼容 3.2 的用户需要做很多处理,总体来说不值当。

iPhone 数据存储

稍微总结一下 iPhone 的数据存储。常见的方式有这么几种:

  1. NSUserDefaults
  2. SQLite
  3. Core Data
  4. iCloud
  5. NSKeyedArchiver/NSKeyedUnarchiver
  6. Keychain
  7. UIPasteboard
  8. writeToFile:

NSUserdefaults

NSUserdefaults 是最为常见的方式,通常用来保存简单的数据,比如 App 设置等。数据保存在 $App/Library/Preferences/$BundleID.plist

// 存
[[NSUserDefaults standardUserDefaults] setInteger:100 forKey:@"MaxCount"];
[[NSUserDefaults standardUserDefaults] synchronize];

// 取
[[NSUserDefaults standardUserDefaults] stringForKey:@"StringKey"];

存数据时候最好 [[NSUserDefaults standardUserDefaults] synchronize]; 来及时保存。

SQLite

iPhone 自带了 SQLite 数据库,可以用来存储大数据量的持久化数据,比如 Google Reader 类阅读器缓存的文章内容。SQLite 直接操作 Api 很复杂,一般都会选用一些开源的 wrapper,比如 FMDB.

Core Data

Core Data 是苹果官方推荐的数据存储方式,底层也是拿 SQLite 做持久化。目前还没有在项目中实践过 Core Data,不多说,官方文档 Introduction to Core Data Programming Guide.

iCloud

iCloud 是 iOS 5 带来的新特性,云端同步是最大的优点,iOS+OS X 通用,可以拿来做一些很神奇的事情,比如 Tweetbot 通过 iCloud 同步 iPhone 和 iPad 上时间线的阅读位置。目前也没有在项目中实践过。

iCloud 可以和 NSUserDefaults 配合使用,比如 MKiCloudSync,sync your NSUserDefaults to iCloud automatically。

NSKeyedArchiver

NSKeyedArchiver 可以将数据 encode 后保存成文件,或者通过 NSUserDefaults 保存;对应 NSKeyedUnarchiver 用来读取数据。适合数据结构复杂(NSArray/NSDictionary)数据量较大但又不需要用 SQLite 做持久化存储的中间缓存,比如 MKNetworkKit 的 freezeOperations 操作,很方便。

// 保存 dict 到 Library 下 Dict 文件
[NSKeyedArchiver archiveRootObject:dict
                            toFile:NIPathForLibraryResource(@"Dict")];
// 读取
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithFile:NIPathForLibraryResource(@"Dict")];

Keychain

Keychain 就是钥匙串,加密保存用户帐号、密码等重要信息。推荐两个 wrapper:SSKeychain, PDKeychainBindingsController

UIPasteboard

UIPasteboard 系统剪贴板是一个非常巧妙的数据存储方式,最大的好处就是可以夸应用数据访问,比如词典应用自动读取翻译剪贴板内容,非常方便。OpenUDID 就是通过一个特殊的剪贴板来保存唯一设备字符串,这样其他 App 就可以用这个唯一标识做设备区分。

writeToFile:

writeToFile: 可以直接将数据写入到指定路径的文件中,NSArray、NSDictionary、NSData 都支持。做数据缓存用的比较多,比如 EGOCache

2012 年中总结

2012 上半年小结。

工作

去年年终总结时候说今年要加强产品锻炼,今年团队也给了这样的机会。第一次作为产品负责人带产品开发,自己却做的很不好,很不及格。产品这一块还有很多很多要学习的地方,分工、协作、沟通、整体、进度等等,在接下来的工作中还要多多学习。

上半年在技术上有了一些新的学习和积累,做了第一个真正意义上的 iPad 应用。大屏幕的体验、使用场景、使用习惯都和 iPhone 有着很大的不同,信息结构有着不一样的处理,对应交互、UI 上有很大的差异,这些差异需要更多的学习理解。开发上由于 iPad 项目是一个全新的项目,尝试了一些新的技术和框架,包括 ARC,新的网络请求方式等。新技术和框架的学习需要一定时间和成本,甚至要交学费,但是从长远来看,这些投入都是值得的,对自己的技术成长很有好处,也有利于团队技术积累。作为开发,如果现在用着和一年前一样的代码做产品,虽然看起来效果一样,但自身的成长非常有限。

作为小团队,机动灵活是自己的特点,也是和大公司竞争的优势,因此在产品开发中要尽快拍板,速度迭代,先简单快速满足 80% 用户的需求,再去精益求精「像素级」地满足剩下 20% 用户。

生活

今年生活中的重头戏就是完婚。结婚是一项庞大的工程,我和妞妞周末忙乎着婚纱照、礼服,爸妈在家忙婚礼安排、婚房装修,有时候还要远程遥控订化妆、摄影。婚礼就是两家人花费忙活,两个人受累上演给别人看得一场秀,表现着家族的威望、实力。如果你能躲过这场秀,那么恭喜你省力很多;如果不能避免,那么何不把这场秀演的更好呢?

上半年陆续有三个兄弟离职回老家工作,称不上「衣锦还乡」,但至少离家近点,毕竟我们都是念家的孩子。对于兄弟们回家工作,我都是双手赞成,虽然我自己还在坚持北漂。有时候我也会问自己到底在坚持什么,那些个梦?那些个理想?那些个自己不愿被这世界改变?我不想等我老了的时候后悔没有拼搏坚持过。

向阳说「成长就是让你从诗人变成世人」。其实,从诗人变成世人,我们都输了。在坚持做自己喜欢的事,还要记住不做让自己讨厌自己的事。最近很多事情让我越来越感受到拒绝比坚持更难。

不知道跟谁学的,现在酒喝多了就满世界打电话,还哭,太差劲。酒量也严重退步,估计结婚的时候该被灌成傻子了。

嗯,以上。

object == nil or nil == object

在 Objective-C 中拿到一个对象后检查对象是否为空,一般有两种写法

一:

if (object == nil) {
    //...
}

二:

if (nil == object) {
    //...
}

这两种写法其实没有任何区别,从代码的可读性上来说第一种 object == nil 方式会好一点。但是推荐用第二种 nil == object 方式,最大的好处就是如果由于笔误 == 写成了 =,编译器会直接报错处理。而 object = nil 不会报错,一旦笔误写成了 object = nil 是很难 debug 查找问题。

via object == nil or nil == object to check whether an object is nil?

2 Years in Beijing

留记。

2010.06.17 到 2012.06.17,很有收获的两年,很有成长的两年。是一个结点,也是新的起点。

postNotificationName with GCD

用 GCD 在后台线程进行下载任务,下载完成后通过 NSNotificationCenter post 一个消息出来,这时候要注意 postNotificationName: 必须要回到主线程进行,不然会引发 crash.

dispatch_async(dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:AnyNotification
                                                        object:nil];
});

resignFirstResponder doesn't work on iPad

在 iPad 上,用 modalPresentationStyle = UIModalPresentationFormSheet 方式推出一个 viewController,这时这个 viewController 不会响应 resignFirstResponder,其他样式的 modalPresentationStyle 没有问题。苹果一个开发在开发者论坛说这是个 feature,不是 bug,devforums.apple.com

Was your view by any chance presented with the UIModalPresentationFormSheet style? To avoid frequent in-and-out animations, the keyboard will sometimes remain on-screen even when there is no first responder. This is not a bug.

就算不是 bug 也很恼人,有人给出了解决方法 devforums.apple.com。新建一个 UINavigationController category,禁掉 disablesAutomaticKeyboardDismissal

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

然后把 viewController 挂在 UINavigationController 下即可:

MyViewController *myViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myViewController];
theNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:theNavigationController animated:YES];

SO 参考: