八 23
NeariPhone, 纯技术 assign, attribute, copy, Objective C, property, readonly, readwrite
一直以来个人觉得如果一个类是的property是readonly的那么再指定其他的如assign/retain/copy这样的属性就实在是没有什么意义了。确实你想想既然都readonly了,肯定是没有setter的,既然没有setter那么谈assign/retain/copy又有什么意义呢?所以一直以来我从来不对readonly的property加retain/copy属性申明,默认assign就足够了,simple is beautiful!
但是我现在发现我错了,其实一直都有一种这种感觉,只是没有找到100%的充分理由为readonly加上retain/copy。但是假如你要在你的subclass改写property,而加入你要改写的是一个NSString,你像把这个属性设置为readwrite和copy,往往杯具就发生了,编译时候可恶的warning 产生了,因为copy和之前默认的assign明显不相同啊!
终上,不论什么时候,都要为你的readonly的对象属性加上合适的retain/copy申明。你现在不用,但不说明你将来就不会用,出来混迟早都要还的!
八 18
NearGeek command键, mac, option键, PC, windows, 键盘
一直以来有这么一种烦恼困扰着我,那就是把pc键盘和mac的兼容性。我之所以喜欢用mac,有很大一个原因是因为mac的commad键位设置得很舒服,每次复制粘贴手不用移动很大位置(不像windows),这个对一个程序员是很重要的。但是每当插上一个windows外界键盘的时候,win键默认为command,而alt默认是option,这就搞得command键位不是很舒服了,作为一个穷学生,又买不起mac外接键盘,只能这样默默地忍受着这种不和谐,心里默默流泪。
但是天晓得,原来mac是支持去修改键盘的command/option键位的,可以让你的pc键盘的commad键和option切换的!这真TMD太人性化了!可我就一直不知道。具体步骤如下:
打开键盘的系统设置,点击modifier keys:

然后选择你要修改的键盘(笔记本会有默认键盘的)

大功告成!享受到了前所未有的快感!
八 17
Near纯技术 Category, Objective C, OC, OCP, Protocol, webservice, 开放封闭原则, 继承
开放封闭原则(OCP)就是,“对扩展开放,对更改封闭”。是所有面向对象设计的一个核心宗旨。感兴趣的可以看百度百科的一些解释:http://baike.baidu.com/view/2493421.htm。
在用Objective C进行开发的时候,OCP当然也是宗旨。利用继承,多态是一个很好的保持OCP的办法,也是最常见的一种方法。Objective C还支持另外两种语法来支持OCP:Protocol和Category。(想要了解Objective c语法的可以看这里:http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html)。
Protocol只能定义一套接口,而不能提供实现,变相的也是一种Abstract class的实现方式(oc 语法上本身不支持抽象基类)。Category可以为类提供额外的接口和实现。那么到底三者(继承, Protocol,Category)在使用上到底有什么本质的区别呢?在我看来,protocol的作用是为一些列类仅仅提供一套公用的接口,而完全没有办法也没可能去提供具体的一些实现情况;category则是为一个已有的类提供一些额外的接口和具体实现;而继承则基于两者之间,既可以想protocol一样提供只是纯粹提供接口,也可以像Category一样提供完整的实现,而且继承还能对类以后的功能进行改写,所以说继承的力量是最强大的。那么具体在使用的时候各自都适合什么样的情况呢?
- Protocol是定义行为而不管谁去怎么实现,这是一种比较洒脱和不负责的情况,就好像在外包项目中的客户一样,他只是他需要什么什么东西,具体实现他不会也不能给出一样。delegate datasource这样的就用protocol实现比较好
- Category是对一个功能完备的类的一种补充,就像是一个东西的主要基本功能都完成了,可以用category为这个类添加不同的组件,使得这个类能够适应不同情况的需求(但是这些不同需求最核心的需求要一致)。找个就像你已经有了一辆能够开动的汽车一样,我们可以用Category为你的汽车添加各种之前没有的功能,最后让这辆汽车变成超级跑车一样。
- 继承则是都可以完成上面的工作,但是继承有很大的代价问题,一是通过继承来进行扩展是一种耦合很高的行为,对父类可以说是完全依赖;二是继承由于对父类依赖,所以开发代价相对大,要求对父类的工作流程相对熟悉;三是继承体系如果太复杂会导致整个系统混乱,难以维护。所以在能够用上面两种方法完成扩展的时候,就千万不要使用继承。什么情况才是迫不得已要使用继承呢?那就是如果你既想提供一系列接口的定义,同时又想提供一些但是又不能提供全部的实现的时候,这种情况就要使用继承了。所以这么看来继承是对上面两种功能的一个黏合剂。
之所以会想到这些,是因为自己在写一个webservice加载库的时候得到的体会。这个库已经提供了一系列最基本的加载webservice的功能,但是不同的程序webservice的api和类型都不是相同的,要怎么才能应用到不同程序中去呢?之前我一直想都不想直接继承了,产生一个新的webservice加载器,然后对不同api分别进行实现。但是每次这么做的时候就发现继承的时候做了很多重复而且没有什么创造性的工作。今天才突然发现了问题的所在,既然我的webservice库已经是一个功能基本齐备的加载器了,为什么我不简单的为这个加载器在不同的程序中创建不用的category呢,然后在复用一些已有的api,不就能够完成工作了吗?确实,我现在通过category的方式减少了之前太多太多的重复劳动,真恨自己为什么没有提早注意到这个问题。
八 15
Near纯技术 instance variable, NSManagedObject, property, 没有实例变量
趁现在还记忆犹新,而且还小有兴奋,把自己怎么实现RT话题写下来。
这个问题其实是在我学习CoreData的时候就一直存在,在CoreData里面有一个“很酷”的类NSManagedObject,只要是找个类的子类,那么这些类的property只要申明并且在.m里面申明为dynamic就可以,而不需要为property指定特定的实力变量,用起来特别方便。这让我这个经常实用property的人觉得真的是匪夷所思啊。一直在想找个玩意儿到底是采用了什么魔法,才能够导致property和实力变量之间的依赖可以剥离。而且前段时间和Kevin同学一起讨论了一下,但是都表示没有头绪。
最近又刚好温习了一下Objective-C Runtime Programming Guide这才恍然大悟,于是花了一天的时间就实现出了类似的效果。并且通过这次实践,对动态语言到底有多动态又有了从来没有过的深入认识,这种感觉很过瘾。
具体是怎么实现的不想多讲,原理不难,过程也不复杂,自己看源代码去,但是要求对oc runtime要有所了解。最终的效果就是我实现一个叫SmartObject 的类,只要是从找个类继承下来的类就可以想NSManagedObject的子类那样不用给出实力变量就可以使用property了!具体使用如下:
1 2 3 4 5 6 7
| #import "SmartObject.h"
@interface TestClass : SmartObject {
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *location;
@property (nonatomic, retain) NSDate *date;
@end |
1 2 3 4 5 6
| #import "TestClass.h"
@implementation TestClass
@dynamic title;
@dynamic location;
@dynamic date;
@end |
结果就可以这样使用了:
1 2 3 4 5 6 7 8 9 10
| TestClass *_myObject;
...
_myObject = [[TestClass alloc] init];
_myObject.title = @"this is title";
_myObject.location = @"this is location";
_myObject.date = [NSDate date];
...
NSLog(_myObject.title, nil);
NSLog(_myObject.location, nil);
NSLog([_myObject.date description], nil); |
感觉是不是很酷啊~
八 06
NeariPhone UIView, 不规则
[申明]本文有点标题党,因为通过本文严格上讲并不能创建一个规则的UIView。
总所周知,UIView都是方形的,并不能产生一个不规则的形状的view(小弟才疏学浅,目前确实没有发现能够创建真实不规则视图的方法,如果有,不吝赐教,感激涕零!)。为什么我们有创建不规则view的需求?如果只是为了在View上显示不规则图形那大可不必,直接讲不规则图形添加到view上,然后讲view的backgroundColor设置为UIColor clearColor就可以;但是之所以有这样的需求,很大部分就是为了判断不规则的图形去响应触摸事件,判断图形是否被触摸选中了这样的要求,我们最直接的想法就是每个不规则图形都是一个view,那么图形是否选中就可以通过UIResponder的那一系列触摸有关的响应函数得知了,所以这个时候我们就需要不规则的view。但是显示的杯具是,iOS并没有提供这样的不规则view,如果要完成刚才的需求,就只能手动判断触摸的点是否在不规则图形里面了,这有的时候将是一件比较痛苦的事情。那么现在提供一种“创建不规则view”的解决方案:
不知道大家有没有注意到UIView有这样一个函数:- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 这个函数就是用来判断指定的点是否在View内,我们方法就是在这个函数中,如果point在指定的不规则图形内返回YES,反之就返回NO。这样不规则图形的bounds就相当于代表了view自己的bounds。这样当你触摸view的时候,当且只有当触摸到指定图形内才会使得view被触摸到,才会调用到UIResponder一系列触摸响应事件。
代码如下:
RoundView.h
1 2 3 4 5 6 7
| @interface MyView : UIView {
UIBezierPath *_path;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
@end |
RoundView.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| // Print current selector's name
#define PRINT_CURRENT_SEL NSLog(@"<%@> %@", NSStringFromClass([self class]),NSStringFromSelector(_cmd))
//
// PrivateMethods
// This category provide private apis for RoundView class
//
@interface RoundView(PrivateMethods)
// Initialize all view's state
- (void)_init;
// Highlight view's border, better visual effect for testing.
- (void) _highlightBorder;
@end
@implementation RoundView(PrivateMethods)
- (void)_init{
[self _highlightBorder];
self.backgroundColor = [UIColor clearColor];
// Create path object as round rect
_path = [[UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, 20, 20) cornerRadius:60] retain];
}
- (void) _highlightBorder{
CALayer *theLayer = [self layer];
theLayer.borderColor = [UIColor blueColor].CGColor;
theLayer.borderWidth = 2;
}
@end
#pragma mark -
@implementation RoundView
- (id)initWithCoder:(NSCoder *)aDecoder{
if((self = [super initWithCoder:aDecoder])){
[self _init];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
[self _init];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setFill];
[_path fill];
}
- (void)dealloc {
[_path release];
[super dealloc];
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
return [_path containsPoint:point];
}
#pragma mark -
#pragma mark UIResponder touches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
PRINT_CURRENT_SEL;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
PRINT_CURRENT_SEL;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
PRINT_CURRENT_SEL;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
PRINT_CURRENT_SEL;
}
@end |
这个demo中用到了3.2以后提供的UIBezierPath类,来创建一个图形的path,在pointInside:withEvent:中判断点是不是在图形的里面,如果是返回YES,反之NO。这样就用找个图形的path代表了view的bounds。那么即使你触摸在view内但是没有在找个图形上,touchesBegan就不会被调用,不会打印相应信息在console中。
所以这样这个view的边界就变成了这个不规则图形的边界了,就变相地创建出了一个不规则的view了!cheers!
七 26
NearGeek apple, letterbox, mac os, mail, plugin, snow leopard, widemail, widescreen
Mail.app一直是个人非常喜欢的收发邮件的工具。但是一直有一点遗憾就是,mail居然没有像microsoft exchange那样可以widescreen模式查看邮件的方式,用户体验和收发效率有点打了折扣。
而且近期mobile me支持这种查看方式,如图:

用户都大呼过瘾,但是苹果一直没有升级可以直接widescreen方式查看的mail,所以笔者心理一直觉得这是一个遗憾。但是,今天阴差阳错在网络上居然发现mail还有plugin可以使mail支持widescreen查看模式,于是尝试了一番,同样大呼过瘾!看截图:

心动了吧!解决方案就是一个叫widemai的plugin:http://widemailplugin.com/ 具体怎么用不说,很简单,自己去体验吧~
PS:再送另外一个plugin,叫letterbox:http://harnly.net/,这个也很不错,但是我个人更偏爱前面一个而已。
七 15
NeariPhone
我觉得这个问题已经烦躁了我很久很久,因为自打我学习Objective c的时候,写这样一句是没有任何问题的:
----------------------
NSString *name = @”Mimi”;
NSLog(name);
而如今升级到SnowLeopard,用上Xcode 3.2之后,如果这么写总是会有一个“format not a string literal and no format arguments”另人烦躁的warning, 虽然比较恶心,但是还是看看为什么会有这个warning再说。
其实一切都是为了安全着想,加入你写了下面的一段程序:
----------------------
NSString *nameFormat = @”%@ %@”;
NSString *firstName = @”Jon”;
NSString *lastName = @”Hess %@”;
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);
那么就相当于
----------------------
NSLog(@”Jon Hess %@”);
这样自然程序运行是有问题的!
所以为了避免这么无辜而且隐蔽的错误,xcode添加了类型检查。
但是如果你觉得你不需要xcode为你操这些心,方便才是王道的话,你可以在xcode里面将GCC 4.2-Warnings中的Typecheck Calls to printf/scanf选项去掉就可以解决问题:

六 27
NearGeek BOBO, iOS4, iPhone, 越狱
今天抱着尝鲜的心理装了回iOS4,当然必须破解了。通过多次尝试,终于用penwtool自制出固件。
虽然手头是一台3G,但是在自制的过程中还是"不自量力"的选择了的所有功能,包括官方iPhone3G并不支持的多任务和壁纸(没有壁纸,这个不能忍啊!用了这么久的“黑频”,为什么不不让爽一次!)等等,总之,统统全开!
最后越狱,unlock,最终可以打电话了。心理暗爽,下面是一些iOS4在iPhone 3G上的用户体验报告:
1. 虚拟键盘的速度明显变了!上次和BOBO在对比虚拟键盘和物理键盘的打字速度的时候,就因为这个原因吃了不少亏。。。
2. 有壁纸就是好看了很多,我最喜欢牛仔裤的背景,赞!
3. 系统中很多新feature都很不错啊!尤其是Folders和升级版Mail。小提示:新的摄像程序居然也支持变焦了!虽然变焦后图片基本很差,但是对偷拍什么的很好用。
4. 多任务在iPhone 3G上体验极其不好,机器很卡很烫,所以也就明白了苹果为什么没有在3G上支持多任务。建议后面要越狱的同学就不要选择多任务了。
5. 电池导航能力:呆报告。就我目前的感觉,电池是撑不了多久的,导航能力应该会下降不少。
。。。。
Anyway,要想用好的系统,还得使用好的设备才行。
六 04
NeariPhone
Schweppes 之前和公司的一个同事一起开发的一个在线音乐播放app,是和Awdio和Schwepps合作的项目。
Awdio是一个很优秀的音乐在线band concert broadcast的网站,这里打一个广告:http://www.awdio.com 有兴趣的可以去看看。
Schwepps我之前一直不知道是什么,今天google才晓得原来是一个汽水品牌,嗯这两个品牌合作开发程序有点意思哦!

程序上架好久了,今天我是今天才知道。下面給出itunes的连接:http://itunes.apple.com/us/app/schweppes-music-by-awdio-com/id368408597?mt=8 有兴趣可以下下来看看。
如果你对这个程序有感兴趣的部分可以告诉我。
PS:目前该app评级都是一星,作为开发者有点伤心啊。看来人是越来越大,但是软件是做得越来越烂了,哎,杯具。。。
五 27
Near其它 BOBO, ixwebhosting, php.ini, 文件大小上限
首先,感谢BOBO给我推荐的使用ixwebhosting,性价比高,而且方便。
然后,就一直在想上传和大伙分享资源的时候犯困了,因为每次wordpress都提示我能上传的文件最大为2M,而一张图片和音乐文件往往都超出了这个限制。所以这个让我心里很懊恼!不知道还有多少爷们姐们还在受苦中!
最后,提出解决方案:网络上有很多人提出了如何突破这个限制的N种方法,像什么修改配置文件等等。其实哪里用得着那么麻烦,最直接的方法就是和ixwebhosting的服务人员直接online chat >>你告诉对方你想要添加上传文件的大小>>然后再告诉对方你的域名>>然后过几分钟对方就告诉你在cg-bin下面给你生成了一个php.ini,你在里面只要修改一下最大文件的大小就搞定了!
上一篇博客就是成功的典范,上传了一个4+M的文件放在我自己的服务器上,再也不用担心url失效了!整个过程大概就一刻钟左右,很顺利,所以特别感谢ixwebhosting,他们的开放精神令人敬佩,不像有些服务商给了你多少上限,你就只能是多少上限,现在我的上限是1G,不过更准确的是说我已经没有上限限制了!
Older Entries
近期评论