属性项目的定义(property)与内存管理问题
来源:互联网 发布:sql数据库查询软件 编辑:程序博客网 时间:2024/05/17 01:44
一些iPhone的系统目录
得到Document目录:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentsDirectory = [paths objectAtIndex:0];
得到temp临时目录:
NSString *tempPath = NSTemporaryDirectory();
得到目录上的文件地址:
NSString *文件地址 = [目录地址 stringByAppendingPathComponent:@"文件名.扩展名"];
iphone程序的开始画面设置
iPhone软件启动后的第一屏图片是非常重要的往往就是loading载入中的意思。设置它说来也简单,但是却无比重要
只需要在resource里面将你希望设置的图片更名为Default.png,这个图片就可以成为iPhone载入的缺省图片
64位编程:整数/小数
对应64位编程的时候,
对于整数应使用NSInteger和NSUInteger,而非int
对于小数应使用CGFloat,而非float
NSInteger其实是一个自动定义,在32位中为int,而64位中为long。CGFloat的原理类似
delegate参数解析
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的事件代理。
此贴暂时就到这里,以后会进行完善,并添加“屏播”解释。
在子类(sub-class)中覆盖“初始化”和“默认”函数
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方法。
对比:id与NSObject
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)
@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是一个非常好的选择。
Objective-C内存管理
1,你初始化(alloc/init)的对象,你需要释放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init];
后,需要
[aArray release];
2,你retain或copy的,你需要释放它。例如:
[aArray retain]
后,需要
[aArray release];
3,被传递(assign)的对象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时: 你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。
为什么不能直接调用dealloc而是release
M 在看过CS193P的笔记后,以下是真正有用的句子:
dealloc不等于C中的free,dealloc并不将内存释放,也不会将索引计数(Reference counting)降低。于是直接调用dealloc反而无法释放内存。
在Objective-C中,索引计数是起决定性作用的。
数据类型/对象类型介绍(1)NSString
字符串是程序设计最常用的数据类型之一了。在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的愉快~
NSString的内存管理
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这个字符串,系统不管。
多线程之NSInvocationOperation
原文: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编程中是经常被用到的。
多线程 之 NSOperation
多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。在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一样!
关于索引计数(Reference Counting)的问题
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的)
对autorelease的误解
A Cocoa的内存管理分为 索引计数法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。而iPhone上目前只支持前者,所以autorelease就成为很多人的“捷径”。
但是!autorelease其实并不是“自动释放”,不像垃圾收集法,对对象之间的关系侦测后发现垃圾-删除。但是autorelease其实是“延后释放”,在一个运行周期后被标记为autorelease会被释放掉。
切记小心使用autorelease,理解autorelease,防止在你还需要该对象的时候已经被系统释放掉了。
Cocoa不同内存管理环境下的autorelease
混合内存管理环境:垃圾收集法(Garbage Collection)+索引计数法(Reference Counting)
虽然大多数情况下混合环境是不被推荐的,但是如果在这个情况下,autorelease需要注意以下事项:
垃圾收集混合环境下:应该使用drain方法,因为release在GC模式下没有意义
索引计数环境下:drain和release对于autoreleasepool(自动释放池)的效果相同
Interface Builder参与的内存管理问题
I 要点:
- 如果一个变量在类中被定义为了 IBOutlet 那么你无需对其进行实例化,xib载入器会对其初始化。
- 如果一个变量在类中被定义为了 IBOutlet 那么你必须负责将其释放。xib载入器不会帮忙的… …
*切不要初始化两回,内存会溢出,而且对象锁定也会出错。
不要对viewController作这样的事情
错误:
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其实也会失去其意义。
最棒的图解MVC
- 控制器是螺丝,控制两头
- 数据控件是硬盘,储存数据
- 视图控件是界面,就是界面… …
- 控制器接收视图的特定行为(target-action)和 代理通告(delegate)
- 控制器和视图接收数据的通知 和 KVO(键值观察)
常用编程快捷键(Xcode/Emacs)
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)
在iPhone上显示LCD效果
我看到一个程序是这样样子的:
哇!好厉害,怎么弄出来的!难道要用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连接到我们建立的对象上
//编译运行!大功告成,还不赶快自己也试试!
- 属性项目的定义(property)与内存管理问题
- 属性项目的定义(property)
- 属性项目的定义(property)
- 属性项目的定义(property)
- 属性项目的定义(property)
- 属性项目的定义(property)copy&retain的区别
- 属性项目的定义(property)copy&retain的区别
- Property 与 内存管理
- @property的内存管理
- oc的内存管理和@property的属性关键字
- @property的内存管理策略©属性修饰符解惑
- iOS内存管理之@property属性详解
- OC @property的内存管理
- 属性与内存管理
- 变量的存储属性与内存管理
- 内存管理与属性的参数
- iOS之属性定义和内存管理
- 项目中关于内存管理的问题
- jQuery在Rails3中的一个简单应用示例
- 7. “1”的个数
- SQL语言的组成执行
- C#中Hashtable的使用
- MongoDB集群
- 属性项目的定义(property)与内存管理问题
- Fedora 14+Eclipse3.6.1+ADT搭建andriod开发环境
- tx_view代码
- c语言中结构体的大小和内存对齐问题
- 2010年9月到12月个人总结回忆
- 林 锐《大学十年 —— 一个程序员的历程》值得成功和欲成功的朋友品读(转载)(上)
- 林 锐《大学十年 —— 一个程序员的历程》值得成功和欲成功的朋友品读(转载)(下)
- Bootloader源码
- FL2440下的流水灯实验