Posts Tagged ‘XCode’
升级到 iDeneb 10.5.8,并解决xcode调试断点问题
Snow Leopard正式版已经发布有一段时间了,看了一下iHackintosh的介绍,升级到Snow Leopard需要一块新的硬盘,作罢。 今天抽空将iDeneb系统升级到10.5.8, 升级过程非常简单,如果已经是10.5.7系统就下载官方更新包Delta update(274MB), 如果是低版本则下载Combo update(759MB)。 在升级之前,还需要下载osx86tools。
在升级之前还需要注意的是备份kext驱动程序, 每次改动之前都做备份是个很好的习惯。 然后按照下面的步骤进行升级,
1. 下载并安装 Disabler.kext (如果是用osx86tools安装,切记不要重新启动)
2. 下载并安装 dsmos.kext
3. 重新启动系统
4. 备份所有的kext, 以便出错后恢复
sudo cp -rf /System/Library/Extensions /System/Library/Extensions_old
5. 打开下载的官方升级程序, 成功后会看到安装成功,是否重新启动的页面,此时不要重新启动,直接进行下一步
6. 运行 osx86tools, 勾选Check repair permissions , Set kext permissions , Clear extensions cache 三项, 然后点击“Run selected tasks”,安装结束会提示重新启动,如果没重启就自己重启系统
在启动时输入参数 -v 查看出错信息,如果一切正常则升级成功。
关于xcode调试时断点不停的问题, 新的voodoo内核虽然解决了断点问题, 但是不能进行step over 和step in等详细调试操作, 网上有人说在启动时输入启动参数: std_dyld=1,我试过但没有用, 做好发现输入参数还需要添加几项,正确的参数应该为:
busratio=20 cpus=1 std_dyld=1
这样在xcode中调试时,断点就可以正常工作了, 而且可以进行step over 等调试操作
提取iPhone程序生成的数据文件
如果你想从iPhone中取出应用程序生成的数据文件, 一般来说有三个方法,
- 使用Jailbreak 版本的iPhone或者ipod touch,安装ssh , ftp或者其他手机软件都可以完成此项任务。 这是最省事最方便的办法,不过严格的说事非法的:)
- 如果程序是你自己写的, 那么在程序中加入upload上传代码,将数据文件上传到指定的服务器
- 如果你是开发人员,只需打开xcode的organizer 即可完成数据文件的提取
对于普通用户,尤其是国内的用户来说,基本上都使用的是Jailbreak版本的水货机, 所以基本上无此烦恼。 而对于开发人员来说,常常需要知道自己的程序在真机上运行的情况以及生成的文件是否是正确的, 毕竟模拟器和真机还是有区别的, 所以第三种办法是最合适的。操作起来很简单。 只需将iPhone连接到电脑上, 打开xcode, 在windows 菜单下选择 Organizer , 然后在左侧选择自己的iPhone标示,在右边的application项中找到需要的程序, 如图

点击左侧小箭头,就会看见Application Data了, 这时只需点击右侧小三角形,就可以将数据文件下载到自己的电脑上了。
iPhone开发之Objective-C学习(5)
Objective-C中的属性
在C++中,类可以有自己的成员变量, 一般公有成员变量可以直接通过类对象访问或修改, 保护成员变量和私有成员变量通过相应的函数来存取,比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class CPerson { public: int gender; protected: int age; public: int GetAge(){return age;} void SetAge( int newValue){ age = newAge;} }; void test(){ CPerson person; person.gender = 0; person.SetAge(20); printf("性别:%d",person.GetAge() ); printf("年龄:%d",person.gender); } |
这里申明一个人的类CPerson, 其中表示性别的变量 gender是公有成员变量,可以通过类对象peron直接读写,而年龄age则需要通过Set和Get函数来读写。 同样的在Objectivie-C中也有类似的机制, 不过在Object-C中默认的变量都是私有的, 而且所有变量都只能通过存取函数或者访问器来访问,而且在Objective-C中把可以通过访问器访问的变量称为属性, 上面的C++ 代码可以用以下Objective-C 来实现
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 | //.h @interface Person : NSObject { int gender; int age; } @property int gender; -(int) GetAge; -(void) SetAge:(int) newValue; @end //.m @implement Person @synthesize gender; -(int) GetAge { return age; } -(void) SetAge:(int) newValue { age = newValue; } @end |
上面的代码中gender就是Person的属性, 如果有对象person则可以通过几种方式读写gender
- person.gender = GenderMale
- printf("性别 %d", person.gender)
- [person setGender:GenderMale];
- printf("性别 %d", [person getGender];
只要申明了属性, 那么就自动拥有get和set访问器,这里很重要的是@synthesize,通过它才可以自动为属性添加访问器,如果自定义了访问器那么@synthesize将不会再次添加。 age变量则需要通过访问函数来存取。
待续。。。
iPhone开发之Objective-C学习(4)
Objective-C的内存管理
在Mac OSX 系列操作系统以及iPhone平台上写应用程序时,打开垃圾回收选项,如果程序并不涉及复杂的内存分配, 就几乎可以不用操心内存管理的问题。系统会自动释放部分不用的内存,就像Java那样。 但是如果所编写的程序中有大量内存分配以及频繁释放使用, 这时就需要自己来管理内存。 也就是说,如果你使用alloc方法为对象分配空间, 就应该在使用完后手动发送release消息以释放内存空间。autorelease自动释放类型无需手动发送release消息,否则会使程序崩溃, 系统会退出在autorelease对象作用域时自动释放相应内存空间。如下面的代码中,
1 2 3 4 5 6 7 | //自动释放类型的对象, 系统会自动释放其内存空间 NSString* str1 = [NSString string]; NSString* str2 = [[NSString alloc] init]; //.. 使用 str2 // 在不使用时发送release消息释放内存空间 [str2 release]; |
Objective-C的内存管理体系引入一种叫引用计数的概念来管理内存,类似C++ COM对象中的引用计数器,当计数器减小到0 时释放内存空间。 简单来说, 在使用alloc创建对象是引用计数为1, 使用retain一次计数加1, 发送release计数减1,如
1 2 3 4 5 | NSString* string = [[NSString alloc] init];//计数为1 [string retain];// 计数为2 //.... [string release]; [string release];// 需要发送release消息两次才能释放内存空间 |
这里有一张来自http://cocoadevcentral.com 的图很生动的解释了这一原理
在平时编写程序是无需去在意引用计数, 只要记住一般情况下只有两种情况下才需要显式发送release消息释放空间
1. 保留变量实例,以供后续使用
2. 函数内创建的临时对象
最后, 记住每使用一次alloc就需要发送release或autorelease消息一次, 每调用一次retain也同样需要release, 只要alloc或者retain 和release或者autorelease成对出现就不会存在内存泄露的可能。
待续…
iPhone开发之Objective-C学习(3)
到现在为止,已经学习了如何调用类方法以及创建对象。 到目前为止我们还没有看到如何才能定义一个类, 上两次的内容已经多次涉及到类及类的成员,现在我们可以学习一下如何才能定义一个自己的类。
设计一个类(接口)
一般来讲创建一个类需要两部分,首先是申明类的头文件ClassName.h, 还有类实现的源文件ClassName.m, 如果你想在程序中混合C/C++编程那么就需要使用.mm或者.M ,这样编译器会以此判断该类中混合了Objective-C 和 C语言。 ClassName.h 头文件中定义类的成员变量以及公有成员函数, 源文件中则包含实际的实现代码,如果你想定义私有函数可以放在实现源文件中,不过需要注意的是必须在该函数被调用调用之前。下面用一个具体的例子来学习如何定义自己的类
1 2 3 4 5 6 7 | #import <Cocoa/Cocoa.h> @interface Friend : NSObject { NSString* name; int age; } @end |
我们从NSObject类继承一个新的类Friend,#import导入Cocoa库的Cocoa.h 头文件, @interface 表示申明一个类定义,也是类定义的开始, 在花括号内是两个成员变量, 最后@end表示类定义结束。对于成员变量可以使用Assessors访问器来访问,也可以申明方法来存取变量
1 2 3 4 5 6 7 8 9 10 11 12 | #import <Cocoa/Cocoa.h> @interface Friend : NSObject { NSString* name; int age; } -(NSString*) getName; -(int) getAge; -(void) setName:(NSString*) newName; -(void) setAge:(int) newAge; @end; |
可以定义存取的方法,如 setName 和 getName。 再来看看实现文件
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 | #import <Cocoa/Cocoa.h> @implement Friend -(NSString*) getName { return name; } -(int) getAge { return age; } -(void) setName:(NSString*) newName { name = newName; } -(void) setAge:(int) newAge { age = newAge; } -(id) init { if( (self=[super init]) ) { [self setName:@"Mike"]; [self setAge:22]; } return self; } -(void) dealloc { [name release]; [super dealloc]; } @end; |
除了要实现定义的成员函数, 还需要重新实现初始化以及析构函数init 和 dealloc, init中的第一行显示由父类来创建一个类对象付给self, 如果成功则给成员变量赋初值, 然后返回self。 在析构释放内存空间时,先把子类中的所有需要释放的对象都release, 然后发送release消息给父类释放内存。
怎么样,定义新类是不是很简单呢? 这里需要注意的几个问题:
- 类定义的开始与结束
由@interface开始,@end; 结束 - 实现类时也需要有开始结束的标致
@implement表示开始, @end;表示结束 - 一般都从NSObject继承定义新类, 否则将需要自己实现初始化以及释放等等代码
- 如果垃圾回收功能处于打开状态, dealloc将不会被调用, 这时需要实现finalize方法
待续。。。
iPhone开发之Objective-C学习(2)
上次学习了Objective-C的基础知识和函数调用的基本规则, 现在我们在来了解一下新的概念——Accessors,简单意思就是访问器。 在Objective-C中所有的类成员变量默认都是私有的, 你不可能直接访问这些成员变量。你需要用setValue 和 getValue或者value来赋值或者取值,你也可以在申明变量时制定setter和getter,下面是Objective-C1.x的语法格式
1 2 | [friend setName:@"Mike"]; value = [friend name]; |
普通情况下你没必要在取值的时候添加get前缀, 实际上每一次调用[friend name]都会发送get消息给对象friend。
从Mac OSX10.5 开始支持O-C2.0, 在O-C2.0 中你可以使用点(.)来对成员变量(属性)进行赋值和取值操作, 比如
1 2 | friend.name = @"Mike"; value = friend.name; |
了解了如何访问类成员变量,我们在来看看如何创建一个类对象。 一般情况下可以有两种方式创建类对象, 第一种是调用类的静态成员创建自动释放对象(稍后会介绍)
1 | NSString* str = [NSString string]; |
调用NSString类的 string 方法返回一个自动释放的对象, 这样赋值很简单,不过要注意对象的作用域,后面将详细介绍自动释放对象。另一种方式是直接分配对象并初始化,如
1 | NSString* str = [[NSString alloc] init]; |
这是一个典型的嵌套调用, 这在上次已经介绍过了, 先是[NSString alloc]分配字符串对象空间, 然后调用init方法初始化, 这样创建的对象需要显式释放,也就是需要调用[str release]去释放内存空间。
待续。。。