得到Document目录:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
得到temp临时目录:
NSString *tempPath = NSTemporaryDirectory();
得到目录上的文件地址:
NSString *文件地址 = [目录地址 stringByAppendingPathComponent:@"文件名.扩展名"];
iPhone软件启动后的第一屏图片是非常重要的往往就是loading载入中的意思。设置它说来也简单,但是却无比重要
只需要在resource里面将你希望设置的图片更名为Default.png,这个图片就可以成为iPhone载入的缺省图片

对应64位编程的时候,
对于整数应使用NSInteger和NSUInteger,而非int
对于小数应使用CGFloat,而非float
NSInteger其实是一个自动定义,在32位中为int,而64位中为long。CGFloat的原理类似
D 在Cocoa里面很多对象的初始化都有一个delegate参数,例如初始化一个ActionSheet
[[UIActionSheet alloc]
initWithTitle:@"标题"
delegate:self
cancelButtonTitle:@"取消按钮"
destructiveButtonTitle:@"结束按钮"
otherButtonTitles:nil];
这里就有一个delegate参数,而我给的例子里面的值是self。
那这个self是什么含义呢?
还有什么其他可行参数么?
答案如下:
1,正如delegate的中文含义是“事件代理”,这里就是要为ActionSheet找一个代理。那么如果写self,那就意味着本地对象和本地类就是这个ActionSheet的“事件代理”。那么我们就应该在这个本地类里面写delegate的方法来回应。例如:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
}
2,本地类如果不是对象类的时候,是没有该对象(ActionSheet)的事件代理解析能力的,这时该怎么办呢?那么就应该在本地类加入对象类的“事件代理”协议(接口),如下:
@interface aViewController : UIViewController <UIActionSheetDelegate>
{
}
这里的<UIActionSheetDelegate>就告诉本地类去接收并可以响应ActionSheet的“事件”
3,如果有多个ActionSheet在一个本地类中,这个事件代理该如果响应呢?
方法如下:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if(actionSheet == 指定的actionSheet对象){}
}
事件代理方法的第一个参数就是发出事件代理的对象,所以可以进行比对后,作if参数调节。
4,delegate后可使用nil值。这个就表示该对象不被代理。
5,delegate后可以使用本地类可以访问的类对象,这样那个类对象就会收到ActionSheet的代理通知。例如:ClassB是ClassA的子类,ClassA中有一个需要代理的ActionSheet, ClassA可以通过这个delegate参数来指定ClassB作为这个ActionSheet的事件代理。
此贴暂时就到这里,以后会进行完善,并添加“屏播”解释。
I 在CS193P中,Evan强调了以下问题:
为什么要在覆盖init的时候需要检查是否在父类中作初始化,例如:
- (id)init
{
if(self = [super init])
{
}
}
或
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
主要是将本地对象用父类的init进行初始化,其中的等号“=”另一方面检查了是不是成功进行了初始化。CS193P提供了更多关于这个的信息:
http://cocoadev.com/index.pl?FactoryMethod
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
不仅仅是init等初始化对象,还有其他一些方法(Method)是需要对自己的父类打声招呼得,例如:
- (void)viewDidLoad {
[super viewDidLoad];
}
那这个没有super这句会怎么样呢?没事,一样用。这个是一个delegate,所以需要收听的类应该会收听到的。但是既然缺省的方法就是这么写的,我们也没有必要特意去删除掉这个super方法。
N 以下是来自CS193P的笔记:
1,id关键字在编译时不被检查,而NSObject在编译时会被检查是否被调用一些错误方法。
2,id可以是任何对象,包括非NSObject对象
3,定义id的时候不使用*,NSObject却需要。
我的理解,基本上来讲,定义id类似于定义了一个地址(只有指针,抽象指针),而NSObject是确实的定义了一个逻辑对象的地址。
一个来自CS193P笔记的链接:
http://unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html
@property (copy, nonatomic) NSString *title;
什么是assign,copy,retain之间的区别?
- assign: 简单赋值,不更改索引计数(Reference Counting),因为基本上是为简单数据类型准备的,而不是NS对象们。
- copy: 建立一个索引计数为1的对象,然后释放旧对象
- retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
Copy其实是建立了一个相同的对象,而retain不是:
比如一个NSString对象,地址为0×1111,内容为@”STR”
Copy到另外一个NSString之后,地址为0×2222,内容相同,新的对象retain为1,旧有对象没有变化
retain到另外一个NSString之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1
也就是说,retain是指针拷贝,copy是内容拷贝。哇,比想象的简单多了
retain的实际语法为:
- (void)setName:(NSString *)newName {
if (name != newName) {
[name release];
name = [newName retain];
// name’s retain count has been bumped up by 1
}
}
说了那么麻烦,其实接下来的话最重要:
?如果你不懂怎么使用他们,那么就这样 ->
- 使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
- 使用copy: 对NSString
- 使用retain: 对其他NSObject和其子类
nonatomic关键字:
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
1,你初始化(alloc/init)的对象,你需要释放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init];
后,需要
2,你retain或copy的,你需要释放它。例如:
后,需要
3,被传递(assign)的对象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时: 你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。
M 在看过CS193P的笔记后,以下是真正有用的句子:
dealloc不等于C中的free,dealloc并不将内存释放,也不会将索引计数(Reference counting)降低。于是直接调用dealloc反而无法释放内存。
在Objective-C中,索引计数是起决定性作用的。
字符串是程序设计最常用的数据类型之一了。在Mac/iPhone编程中,苹果为我们提供了一个不同的字符串类型NSString。有别与普通的String为数据类型,NSString其实是一个对象类型。NSString是NSObject(Cocoa Foundation的基础对象)的子类,所以具有NSObject的所有特性,好的和好的… ….
小常识:
NS是Cocoa类对象类型的前缀,来源于史蒂夫-乔布斯被苹果开除那段时间建立的公司NeXT.
@是Cocoa元素的前缀,很多地方我们会看到,比如接下来...
1, 创建一个NSString对象
简单方法:
NSString *aString = @"我是个NS字符串!"; //除了引号外加@, 没别的区别
*上面的不需要操心内存管理哟~
复杂一点儿:(需要内存管理的)
NSString *aString = [[NSString alloc] initWithFormat:@"这也是个NS字符串!"];
*initWithFormat是其中一个初始化方法,常用的还有
//从一个文件读取需要的内容
- (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
//从一个地址读取需要的内容
- (id)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error
*以上方法得到的NSString的retain值为1,所以记得release掉阿~~
2,使用一个NSString对象
NSString *aString = @"This is a NSString";
NSLog(aString); //在控制台输出信息,该函数方法需要一个NSString对象作为参数
NSLog("这样不会好使的");
NSLog(@"这样就会好使拉~");
再比如设置一个UIView的标题:
[UIView setTitle:aString];
[UIView setTitle:@"标题"];
UIView.title = aString;
3,释放NSString
[aString release]; //对象将被系统释放掉咯
*记得不要释放直接用 = @”xxx” 的NSString对象哟,系统会管的~
4,快速使用一个NSString
NSLog([NSString stringWithFormat:@"一个NS字符串"]);
//这种快速方法返回的是一个retain为1,autorelease的对象,不需要操心它的内存管理
5,常用方法
我喜欢NSString的地方就在于很多方法非常方便,比如:
nString = [aString substringToIndex:4]; //nString将得到aString中的前四个字符
6,小结
暂时能记起来的就这么些了,有机会再补充,希望大家NS的愉快~
CS193P的笔记上有如下实例:
aString = @"I am a string that 2 years old, man!";
这种情况下,字符串储存和管理由系统做,我们不用操心。
aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];
第二种情况下,我们需要去retain和release这个字符串,系统不管。
原文:http://c.gzl.name/archives/category/cocoa/cobjc
T 多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。在Cocoa中,Apple提供了NSOperation这个类,提供了一个优秀的多线程编程方法。
本次介绍NSOperation的子集,简易方法的NSInvocationOperation:
@implementation MyCustomClass
- (void)launchTaskWithData:(id)data
{
//创建一个NSInvocationOperation对象,并初始化到方法
//在这里,selector参数后的值是你想在另外一个线程中运行的方法(函数,Method)
//在这里,object后的值是想传递给前面方法的数据
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(myTaskMethod:) object:data];
// 下面将我们建立的操作“Operation”加入到本地程序的共享队列中(加入后方法就会立刻被执行)
// 更多的时候是由我们自己建立“操作”队列
[[MyAppDelegate sharedOperationQueue] addOperation:theOp];
}
// 这个是真正运行在另外一个线程的“方法”
- (void)myTaskMethod:(id)data
{
// Perform the task.
}
@end
一个NSOperationQueue 操作队列,就相当于一个线程管理器,而非一个线程。因为你可以设置这个线程管理器内可以并行运行的的线程数量等等。下面是建立并初始化一个操作队列:
@interface MyViewController : UIViewController {
NSOperationQueue *operationQueue;
//在头文件中声明该队列
}
@end
@implementation MyViewController
- (id)init
{
self = [super init];
if (self) {
operationQueue = [[NSOperationQueue alloc] init]; //初始化操作队列
[operationQueue setMaxConcurrentOperationCount:1];
//在这里限定了该队列只同时运行一个线程
//这个队列已经可以使用了
}
return self;
}
- (void)dealloc
{
[operationQueue release];
//正如Alan经常说的,我们是程序的好公民,需要释放内存!
[super dealloc];
}
@end
简单介绍之后,其实可以发现这种方法是非常简单的。很多的时候我们使用多线程仅仅是为了防止主线程堵塞,而NSInvocationOperation就是最简单的多线程编程,在iPhone编程中是经常被用到的。
多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。在Cocoa中,Apple提供了NSOperation这个类,提供了一个优秀的多线程编程方法。
本次讲解NSOperation的使用方法:
1,将想在另外一个线程的工作单独成类,并设置其父类为NSOperation:
@interface ImageLoadingOperation : NSOperation {
NSURL *imageURL; //这个例子里面需要传入一个图片地址,所以定义一个NSURL变量
id target; //由于需要返回一些值,所以需要一个对象参数返回要被返回的对象(运行此线程的类对象)
SEL action; //返回值要激发的方法函数
}
2,借由其初始化方法来传入所需要的参数和对象
- (id)initWithImageURL:(NSURL *)theImageURL target:(id)theTarget action:(SEL)theAction
{
self = [super init]; //在老帖里面解释过为什么需要这么做了
if (self) {
imageURL = [theImageURL retain]; // 拷贝进对象,并retain(为什么?请查老帖)
target = theTarget;
action = theAction;
}
return self;
}
呼叫这个类对象的时候,传入所需要的参数和对象
// 这些是需要对其初始化的类中的代码
ImageLoadingOperation *operation = [[ImageLoadingOperation alloc] initWithImageURL:url target:self action:@selector(didFinishLoadingImageWithResult:)]; //初始化
[operationQueue addOperation:operation]; //添加到运行队列
[operation release]; //由于队列对其retain,所以我们需要release它
3,在我们的线程操作类中的main函数执行所需要的工作
- (void)main
{
// 同时载入图片
NSData *data = [[NSData alloc] initWithContentsOfURL:imageURL];
UIImage *image = [[UIImage alloc] initWithData:data];
// 打包返回给初始类对象,然后执行其指定的操作
NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:image, ImageResultKey, imageURL, URLResultKey, nil];
[target performSelectorOnMainThread:action withObject:result waitUntilDone:NO];
[data release]; //不需要了就清理
[image release];
}
这些就是一个简单的NSOperation的使用过程了。其实看看嘛,非常简单的,正如苹果为我们准备的其他API一样!
M *retain值 = 索引计数(Reference Counting)
- NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类(Collection Classes)都执行类似操作。例如NSDictionary,甚至UINavigationController。
- Alloc/init建立的对象,索引计数为1。无需将其再次retain。
- [NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象。所以是本地临时对象,那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。
- 缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray)
- 在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,而retain值为1的)
A Cocoa的内存管理分为 索引计数法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。而iPhone上目前只支持前者,所以autorelease就成为很多人的“捷径”。
但是!autorelease其实并不是“自动释放”,不像垃圾收集法,对对象之间的关系侦测后发现垃圾-删除。但是autorelease其实是“延后释放”,在一个运行周期后被标记为autorelease会被释放掉。
切记小心使用autorelease,理解autorelease,防止在你还需要该对象的时候已经被系统释放掉了。
混合内存管理环境:垃圾收集法(Garbage Collection)+索引计数法(Reference Counting)
虽然大多数情况下混合环境是不被推荐的,但是如果在这个情况下,autorelease需要注意以下事项:
垃圾收集混合环境下:应该使用drain方法,因为release在GC模式下没有意义
索引计数环境下:drain和release对于autoreleasepool(自动释放池)的效果相同
I 要点:
- 如果一个变量在类中被定义为了 IBOutlet 那么你无需对其进行实例化,xib载入器会对其初始化。
- 如果一个变量在类中被定义为了 IBOutlet 那么你必须负责将其释放。xib载入器不会帮忙的… …
*切不要初始化两回,内存会溢出,而且对象锁定也会出错。
错误:
UIViewController *aViewController = [[UIViewController alloc] init];
[window addSubview:aViewController.view];
[aViewController release];
这样的话,系统会崩溃的… window或着其他父视图是不会retain整个viewController的,这个时候不能立刻release
正确:
[aViewController.view removeFromSuperview];
[aViewController release];
也就是说,在release之前需要从superview中移除这个viewController的view。如果一直都需要这个view,那就在dealloc里面作这些事情就可以了
问题一:
value = [array objectAtIndex:n]; //得到一个数组中的对象
[arry removeObjectAtIndex:n]; //卸载那个对象
因为value得到了那个对象,但是由于另外一个拥有者release了该对象,所以其实value现在成了摇摆指针(无效数据)
问题二:
myArray = [NSArray array];
...
[myArray release];
NSArray返回的是一个自动释放对象,不仅myArray不应该在一段时间后release,而应该在适当的时候先retain,以防止该array被系统误释放。
问题三:
rocket = [rocketLauncher aRocket];
[rocketLauncher release];
和array这种数据收集类对象一样,如果我们得到了一个类的子对象而不retain它,那么在原父类被释放的时候,这个rocket其实也会失去其意义。

- 控制器是螺丝,控制两头
- 数据控件是硬盘,储存数据
- 视图控件是界面,就是界面… …
- 控制器接收视图的特定行为(target-action)和 代理通告(delegate)
- 控制器和视图接收数据的通知 和 KVO(键值观察)
control-F: 向右一个字符(forward)
control-B: 向左一个字符(backward)
control-P: 前一行(previous)
control-N: 后一行(next)
control-A: 去行首
control-E: 到行尾(end)
control-T: 调换光标两边的字符(transpose)
control-D: 删除光标右侧字符(delete)
control-K: 删除本行剩余的字符(kill)
control-L: 居中插入点到屏幕中央(lock)
我看到一个程序是这样样子的:

哇!好厉害,怎么弄出来的!难道要用Q2D画出来么?
不… …
其实这就是UILabel外加一个奇异的字体 DBLCDTempBlack
And, that’s it! 生活多么美好阿
R 来做一个小小随机数生成器吧!从1-100~
***Safari浏览的时候似乎会很乱… 换Firefox看这个帖子吧
//
// rndNo.m
// RandomNumber
//
// Created by Zhengliang Guo on 09-6-17.
// Copyright 2009 gzl.name All rights reserved.
//
这个程序非常简单,首先建立一个类,选一个自己喜欢的名字:


看看头文件里面有什么呢?
@interface rndNo : NSObject {
IBOutlet NSTextField *textField;
}
-(IBAction)resetSeed:(id)sender;
-(IBAction)genderateNo:(id)sender;
@end
m文件里面的洞天:
-(IBAction)resetSeed:(id)sender{
srandom(time(NULL));
[textField setStringValue:@"随机数种子已重置"];
}
-(IBAction)genderateNo:(id)sender{
[textField setIntValue:(random()%100 +1)];
}
在IB里面建立一个对象,然后指定他的类为我的rndNo.

//记得将IBAction和IBOutlet连接正确噢~否则不会好使的。
//不会在Xcode里面连接对象?在我的博客里面搜索一下吧!
让我们的程序在点击关闭红点的时候也关闭吧:
首先添加所需的事件代理到m文件:
- (void)windowWillClose:(NSNotification *)notification //当窗口关闭的时候
{
exit(1); //我们退出程序
}
右键点击我们的窗口,然后将delegate连接到我们建立的对象上
