Archive for 九月 2009

生活,生计

短短几天感觉自己老了好几岁,由于心情不好,减了10斤肉(因祸得福… 吧)。最近恐怕要迫于生计干和学一些非Mac开发的东西了,有些是老课题了,Cisco。曾经的挑战以失败落幕,不过未来的挑战在胜利之前是不会有落幕的时刻。

不知道自己现在是为了爱情,还是为了生计,或是为了将来。不过一如既往的努力,和100%的工作是我现在需要的了。

在完全备考CCIE之前,《我的佛典》还是需要一个更新升级的,需要更好的使用本地存储来解决新数据载入的问题,所以Core Data还会是我的讨论主题和研究方向。如何简单的整理数据,以便方便的增量更新也是个问题。

今天非常开心有一位佛友发了eMail给我,教我“郭师兄”。师兄当然是称不上了,但是我非常非常开心。新版MyFodian一定要完成,而且要尽快完成!

数据类型/对象类型介绍(2)UINavigationController

UINavigationController iPhone导航控制器/导航栏 是在iPhone程序中广为使用的用户数据互动方式。

屏幕快照 2009-09-06 下午04.17.41

这是一个简单的导航栏截图,我们可以设置其内置UIView的title,而导航栏会显示出这个title。而不是设置导航栏的title。我们也可以设置其左侧,或者右侧的按钮或者自定义视图对象。我们下面来一步一步的看看导航栏的使用:

1,创建并使用一个UINavigationController

UINavigationController *aNav = [[UINavigationController alloc] init];

然后添加一个视图进去,否则导航栏也没有意义的

UIViewController *aView = [[UIView alloc] initWithNibName: (*xib文件名*)];
[aNav pushViewController:aView animated:NO];
//导航栏的第一个视图不要动画化

2,设置导航栏的左右按钮:
我说过,设置导航栏的按钮并不是去设置导航栏本身,而是当时被导航的视图控制器,比如我们对aView作设置。

设置其标题:

aView.title = @"标题";
 
//配置一个按钮,我这里是《我的佛典》上的代码
UIBarButtonItem *callModalViewButton = [[UIBarButtonItem alloc]
							initWithTitle:@"经文"
							style:UIBarButtonItemStyleBordered
							target:self
							action:@selector(callModalList)];
self.navigationItem.leftBarButtonItem = callModalViewButton;
[callModalViewButton release]; //由于本地视图会retain它,所以我们可以release了

可以看到,还是很简单的嘛。

3,其他常用方法和属性:

本地视图.navigationItem.leftBarButtonItem //左边栏项目
本地视图.navigationItem.rightBarButtonItem //右边栏项目
本地视图.navigationItem.backBarButtonItem //后退栏项目
本地视图.navigationItem.hidesBackButton //隐藏后退按钮(YES or NO)

作为iPhone开发中最常用的对象之一,还有很多内容值得挖掘,不过今天就到这里了。祝愿大家在iPhone编程之路上一路快走!

makeKeyAndVisible

我不知道为什么,不过有人搜索makeKeyAndVisible方法。其实我这种懒人一般不会刨根问底,有些方法照打就好,那些白给的方法有些就别动就好了。

我们看看这个每个程序都有的方法吧:

[window makeKeyAndVisible];

由于iPhone是单窗口程序,所以也就只有这么一个Window对象,而且是UIWindow,不是NSWindow。而根据文档上所说:

“这个是便捷方法,去使被使用对象的主窗口显示到屏幕的最前端。你也可以使用hiddenUIView方法隐藏这个窗口”

所以基本上来说,对于编程者的区别仅仅在于在其前添加代码,或在其后添加代码。

Three20添加方法(翻译)

Three20是一个iPhone开发图形接口类的集合,包含图片查看,一般工具,HTTP本地缓存。Three20是来自于Facebook的iPhone程序源代码的。

添加Three20到您的程序
==============================

Three20是预编译静态库,最简单的方法是使用Xcode的依赖工程特性,下面是方法:

1. 复制(Clone命令)three20 git(GitHub) 目录: `git clone git://github.com/joehewitt/three20.git`.  确保将其储存在一个常用位置,以便Xcode每次编译时来索引和访问

2. 在 “three20/src”中找到 “Three20.xcodeproj” . 拖拽Three20.xcodeproj到您工程的根目录”Groups and Files”边栏中.在弹出对话框中去掉”Copy items”的对号,”Reference Type”选择”Relative to Project”然后点“Add”.

3. 现在要链接Three20库到您的工程。点击添加进来的”Three20.xcodeproj”,在“Details”表中,你会看到 libThree20.a. 打上文件右侧的对号

4. 现在你需要设置320库为你程序的依赖库,以便Xcode在编译的时候也会将320一起编译起来。展开左侧的“Targets”标签,双击您程序的“目标”文件。在“General”标签下,你会看到“Direct Dependencies”,点“+”号添加320库。

5. 现在你需要添加图片和字符串包到你的程序,找到”Three20.bundle”在”three20/src”中,然后拖拽到你的程序中。对话框里面“Copy items”别选,“reference type”选“relative to project”

6. 现在,你需要添加 Core Animation framework到你的工程。点击程序target,然后在frameworks里面添加 QuartzCore.framework就可以了(这个不是翻译的,原来的方法太麻烦了

7. 最后,我们需要让你的工程找得到320库的文件头。打开 “Project Settings”找到”Build”标签,找到 “Header Search Paths”双击它。添加到”three20/src”相对目录的地址。

8. 当你在 Project Settings, 找到 “Other Linker Flags”在”Linker”区,添加”-ObjC”和”-all_load”。

9. 完活了,在用320库的地方添加 #import “Three20/Three20.h” 就好了。

在iPhone程序上读取PDF文件 (rev0.1 ^-^;)

老话,最近闹心的事情多,开心的事情少,但是正事还是要干的。学习得需要,努力的需要,钱的需要… … 天上给我下点儿钞票吧!


言归正传,怎么在iPhone程序中读取PDF的内容呢?答案是,苹果为我们准备了一个很神奇的framework Q2D(Quartz 2D)。Q2D提供了全套的PDF读取API,接下来我们来看看如果简单的使用Q2D来读取PDF文件:

我建立了一个工程叫iPhonePDF, 添加了一个UIScrollView(不知道怎么添加UIScrollView? 添加一个UIView然后把interface上的UIView改成UIScrollView就可以啦…)名为PDFView

看看PDFView里面有什么吧

@interface PDFView : UIScrollView {
 
	NSString *filePath;
	CGPDFDocumentRef pdfDocument;
	CGPDFPageRef page;
	int pageNumber;
}
 
@property (copy, nonatomic) NSString *filePath;
@property int pageNumber;
 
-(CGPDFDocumentRef)MyGetPDFDocumentRef;
-(void)reloadView;
-(IBAction)goUpPage:(id)sender;
-(IBAction)goDownPage:(id)sender;
@end

filePath是储存pdf文件的位置的,得到文件位置就是老话题了:[NSBundle mainBundle]… 后面的会写吧… 不记得了在我博客里面搜索吧

CGPDFDocumentRef是PDF文档索引文件,Q2D是Core Foundation的API,所以没看到那个星星~

CGPDFPageRef是PDF页面索引文件

pageNumber是页码

下面的几个函数其实一看就明了了,翻页的,和刷新页面的。第一个是自定义的getter

然后我们看看m文件里面有用的方法:

@implementation PDFView
@synthesize filePath,pageNumber;
 
- (void)drawRect:(CGRect)rect //只要是UIView都有的绘图函数,基础哟~
{
	if(filePath == nil) //如果没被初始化的话,就初始化
	{
		pageNumber = 10;   //这个其实应该由外部函数控制,不过谁让这个程序特别简单呢
		filePath = [[NSBundle mainBundle] pathForResource:@"zhaomu" ofType:@"pdf"];
                //这里,文件在这里!
		pdfDocument = [self MyGetPDFDocumentRef]; //从自定义getter得到文件索引
	}
 
	CGContextRef myContext = UIGraphicsGetCurrentContext();
        //这个我研究了一段时间呢,不过就照打就可以了
 
	page = CGPDFDocumentGetPage(pdfDocument, pageNumber);
        //便捷函数,告诉人家文档,告诉人家页码,就给你页面索引
 
	CGContextDrawPDFPage(myContext, page);
        //画!
}
 
//此getter可以考虑照打... 都是CF函数,我看到就恶心。
//其实不是很难了,得到文件,转换成URL,然后通过
//CGPDFDocumentCreateWithURL(url)得到文件内容索引
//Ta Daaa~~
- (CGPDFDocumentRef)MyGetPDFDocumentRef
{
	CFStringRef path;
	CFURLRef url;
	CGPDFDocumentRef document;
	path = CFStringCreateWithCString(NULL, [filePath UTF8String], kCFStringEncodingUTF8);
	url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0);
	CFRelease(path);
	document = CGPDFDocumentCreateWithURL(url);
	CFRelease(url);
	return document;
}
 
-(void)reloadView
{
	[self setNeedsDisplay]; //每次需要重画视图了,就call这个
}
 
-(IBAction)goUpPage:(id)sender
{
	pageNumber++;
 
	[self reloadView];
}
-(IBAction)goDownPage:(id)sender
{
	pageNumber--;
	[self reloadView];
}
@end

我这个是个少半成品的程序呢… 我当时弄了几个PDF测试程序,但是找不到了。不过意思是一样的,剩下的东西由大家来发挥吧,有问题记得留言噢!我有问必答!

与开发无关:魔兽世界,你还要害死多少人?

如果按照美国的规矩写文章,我恐怕就必须证明魔兽世界已经害死了多少人。但是我是中国人,我用中国字,我看到的是中国人能看到的。

是阿,魔兽世界不是唯一一个网络游戏,就算没有魔兽世界,在地球上还有那么多其他的网络游戏。但是这种假设没有必要,因为魔兽世界是现实存在的,而且已经害了很多人,我其实就是间接受害者。

不懂究竟魔兽世界有多好玩,不懂玩魔兽世界的人内心到底有多空虚。不懂魔兽世界究竟能带来怎样的快感,不懂魔兽玩家究竟能从中得到什么?我真是不懂阿!我没玩过?我玩过,为了学习其中宏怎么写,lua怎么用,但是最后发现不过是在帮wow害人而已。

是阿,我们的社会压力太大了,我们的家庭压力太大了,我们的学校压力太大了,该死的学习压力太大了。压力大还有很多方式方法来解决,压力大也不应该玩上就不停歇,压力再大这也是现实。魔兽中的一切的一切都是虚幻泡影,金币,银币,铜币,你最后真能用他们换来什么么?

醒来吧,醒来吧,不知道该用什么拯救你。醒来吧,醒来吧,现实还需要你来面对。

循环使用整个NSArray内的对象

循环使用整个NSArray内的对象是非常常用的了,而且最近我在研究究竟怎么能方便的把NSArray存入Core Data,所以这更是必要了,看看如下的方法吧:

1,Objective-C 2.0法,最应该使用的

NSArray *aArray; //我们的Array,假设他已经初始化有内容了
 
for(id innerObj in aArray) //id可以由其他对象类型替代
{
//也就是说, 在循环中的参数innerObj就是aArray中的对象
//由于NSArray中只能储存对象,所以我们使用id作为内涵对象的类型,其实就是个指针了
//而且如果NSArray中的内容不一致,id更不会出现冲突
}

2,C的老方法,不推荐,低性能

NSArray *aArray; //我们的Array,假设他已经初始化有内容了
 
for(int i=0;i<[aArray count]; i++)
{
[[aArray objectAtIndex:i] 然后作你想作的事情]; //做爱 作的事情...
}

3, 用NSEnumerator(不知道怎么翻译阿….)

 NSEnumerator* myIterator = [myArray reverseObjectEnumerator];
 id anObject;
 
 while( anObject = [myIterator nextObject]) //每次读取“逐读器”的下一个对象
 {
     //anObject和刚才的innerObj是一个意思,但是看看多了这么多行
 }

结语:
就用第一种方法吧….

答问留言:关于NSOperation

1,operationQueue 里边应该可以同时添加多个operation吧?

是的,本来operationQueue的目的就是多线程管理,那多线程,可只是一个线程。

而且我们可以设置这个队列每次被处理的“操作”数量

	NSOperationQueue *aQ = [[NSOperationQueue alloc] init];
	[aQ setMaxConcurrentOperationCount:10];

这里的setMaxConcurrentOperationCount就是同时被处理的“操作数”,参数为整数int或NSInteger (两个是一样的,不记得的可以在我的博客里面搜索一下噢~)

2,那main函数应该怎么写?

main函数中其实只需要写你要在另外一个进程里面作的事情。比如对于我来说,我常常只是作一个简单的事情,那我会用NSInvocationOperation,NSOperation的简化版。比如说:

NSInvocationOperation *aOpt = [[NSInvocationOperation alloc]
		 initWithTarget:self selector:@selector(doSomeThing) object:nil];
 
- (void)doSomeThing
{
    //读取大量大延迟数据等等
    //可以使用performSelectorOnMainThread来将得来的数据返回到主线程
}

在doSomeThing函数里面,我可以从网上读取一些东西,但是读取是需要占用时间,而堵塞主线程的。而使用NSOperation这样使用就不会了。

而如果是NSOperation,虽然复杂了一些,又是做一个NSOperation的子类。其实main函数做得事情和doSomeThing是一抹一样的。只不过如果你制作这个子类,你对其操作的内容可以更多,可以制作更复杂的读取,载入操作等等,而且你可以重复使用这个类功能阿。再者,NSOperation也提供了对runtime操作的支持,不过那就太麻烦了,一般不大用的上。


最近麻烦事情真是太多了,而且还都不顺利,死的心都有阿。还好有这么多好朋友支持我,我这个博客也一点儿一点儿的有回复了…大家别那么冷漠,管我写的好还是不好,按东北话来说“吱一声”嘛~唉,我要加油阿!我还有那么多的事情没办到呢,怎么能放弃!他妈的!!!!!阿!!!!!!

从0开始Core Data(1)

大家都有Snow Leopard和XCode 3.2了吧?会发现XCode变了不少,帅拉!

屏幕快照 2009-09-01 上午11.58.22

那我们点击“Create a new Xcode project”来开始我们的Core Data程序工程吧!

屏幕快照 2009-09-01 下午12.06.52

在这里,XCode已经给我们准备好了一个几乎可以直接去用的程序模板,直接选择“基于导航的应用程序”,然后记得点选“Use Core Data for storage”

屏幕快照 2009-09-01 下午12.14.03

建立好的程序名为XCDtest01,我们尝试编译运行,看看得到的程序是什么样的:

屏幕快照 2009-09-01 下午12.16.47

基本上来说,这个程序把什么都给我们弄好了,一个程序,在点击添加按钮之后添加现在的时间标签,如果点击“Edit”编辑按钮,就进入编辑模式,可以删除任意条信息。

如果点开xcdatamodel文件,我们可以看到,其中的实体为Event,有一个参数,名为“时间标签”。也就是说,如果我们想对这个列表视图中的数据作更改,只需要适当更改这个实体的参数,并配置- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 代理条目就可以显示适当的内容了。

屏幕快照 2009-09-01 下午12.20.19

这个预置程序与我们之前讨论的程序不同的,在于这个程序中并没有配置一个可变数组(NSMutableArray)来作数据副本,以达到高速存储的目的。因为Core Data在向磁盘和内存操作,NSMutableArray是内存操作,速度上比较有优势。但是我们有的这个小程序太小了,再者苹果有可能认为那种方法是非标准的。所以在这里才没有那么作

NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@"timeStamp"] description];

在这个程序的cell配置代理里面,仅仅是从“获取操作控制器”中得到了“被管理对象”,然后再读取其中的内容到cell的text中。

希望大家也使用这个模板,自己创建一个Core Data程序,然后简单的理解一下代码。下次我们聊只使用基于Window的程序模板+Core Data来创建程序

预告(Core Data)

今天晚些时候或者最近会一步一步的制作一个简单的Core Data程序。Core Data确实是个好玩的东西,不多写写是不行的。


最近心情比较差,失恋都失恋大发了,就像饿过了就不饿了~感觉人又成熟了,看多了,见多了,想多了,悟道的也就多了

借郭德纲的定场诗:

守法朝朝忧闷,强梁夜夜欢歌。

损人利己骑马骡,正直公平挨饿。

修桥补路瞎眼,杀人放火儿多。

我到西天问我佛,佛说——我也没辙。

再借某人的博客上的话(http://blog.sina.com.cn/s/blog_5e60c5b60100df90.html)
是的,没辙。很多事情是没辙。但世上本是没有辙的,走的车多了,就有辙了。所以,光感叹没辙是没辙的。有辙的唯一办法就是——发动车,上路。

他说得不错,有功夫想辙,还不如直接去干,直接去做。发动车是不行了,我手头还没车,人家都有跑车了… 作自己能做得,做到最好吧!管它三七21,九九81,缘亦如此矣,报应如此矣。

皈依我佛,皈依法性,再不行就自皈依僧当个高科技和尚吧,哈哈~