object-c笔记

来源:互联网 发布:复旦大学有网络教育 编辑:程序博客网 时间:2024/06/12 22:43

iOS笔记

Categories

CategoriesObjective-C里面最常用到的功能之一。基本上category可以让我们给已经存在的类增加方法,而不需要增加一个子类。而且不需要知道它内部具体的实现。

如果我们想增加某个framework自带的类的方法,这非常有效。如果我们想在我们程序工程的NSString能够增加一个方法,我们就可以使用category。甚至都不需要自己实现一个NSString的子类。

比如,我们想在NSString里面增加一个方法来判断它是否是一个URL,那我们就可以这么做:

#import

@interface NSString (Utilities)

- (BOOL) isURL;

@end

这跟类的定义非常类似。区别就是category没有父类,而且在括号里面要有category的名字。名字可以随便取,但是习惯叫法会让人比较明白category里面有些什么功能的方法。

这里是具体的实现。但是要注意,这本身并不是一个判断URL很好的实现。我们主要是为了整体的了解category的概念。

#import "NSString-Utilities.h"

@implementation NSString (Utilities)

- (BOOL) isURL

{

if ( [self hasPrefix:@"http://"] )

return YES;

else

return NO;

}

@end

现在我们可以在任何的NSString类对象里都可以调用这个方法了。下面的代码在console里面打印的"string1 is a URL"

NSString* string1 = @"http://www.CocoaDev.cn/";

NSString* string2 = @"Pixar";

if ( [string1 isURL] )

NSLog (@"string1 is a URL");

if ( [string2 isURL] )

NSLog (@"string2 is a URL");

跟子类不一样,category不能增加成员变量。我们还可以用category来重写类原先的存在的方法,但是这需要非常非常小心。

记住,当我们通过category来修改一个类的时候,它对应用程序里的这个类所有对象都起作用。

隐藏xcode command+h

退出xcode command+q

关闭窗口 command+w

关闭所有窗口 command+option+w

关闭当前项目 command+control+w

关闭当前文件 command+shift+w

保存文件 command+s

保存所有文件 command+option+s

?

还原到保存时状态 command+u

?

项目中查找 command+shift+F

查找下一个 command+g

查找上一个 command+shift+g

浏览源文件 command+Double Click

打开头文件 command+shift+d

切换头/源文件 command+option+上箭头

撤销 command+z

重复 command+shift+z

粘贴并匹配格式 command+option+shift+v

文件首行 command+上箭头

文件末 command+下箭头

行首 command+左箭头

行末 command+右箭头

上一单词 option+左箭头

下一单词 option+右箭头

上一拆分单词 control+左箭头

下一拆分单词 control+右箭头

?

Tab :接受代码提示

Esc :显示代码提示菜单

下个Build警告或错误 command+=

前个Build警告或错误 command+shift+=

以调试方式运行程序 command+y

继续(在调试中)command+option+p

编译运行 command+r

Xcode 代码格式化/自动排版:

Xcode 版本:4.24.2之前的版本

选中需要格式化代码 -> Edit -> Format ->Re-Indent

Xcode 版本:4.2之后的版本

选中需要格式化代码 -> Editor -> Structure ->Re-Indent 或者

选中需要格式化代码 -> 右击 ->选中 Structure ->Re-Indent

nonatomic assign retain copy readonly readwrite //对象的创建和使用;

singleton

alloc copy retain release autorelease strong weak //堆栈内存管理

kvc kvo NSNotificationCenter NSNotification

category Extention protocol

Objective-C中类属性的 copy, retain, assign , readonly , readwrite, nonatomic区别

nonatomic:非原子性访问,对属性赋值的时候不加锁,多线程并发访问会提高性能。如果不加此属性,则默认是两个访问方法都为原子型事务访问。

atomicObjc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。)

assign: 简单赋值,不更改引用计数

对基础数据类型 (例如NSInteger)和C数据类型(int,float, double, char, 等) 适用简单数据类型或对指针的弱引用

copy:建立一个索引计数为1的对象,然后释放旧对象对NSString

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

对其他NSObject和其子类

@property (nonatomic, assign) int number;

这里定义了一个int类型的属性,那么这个int是简单数据类型,所以用nonatomic, 不需要进行引用计数,所以用assign。适用于简单数据类型和指针的弱引用。

@property (nonatomic, copy) NSString * myString;

这里定义了一个NSString类型的属性,不需要原子操作,所以用nonatomic.

为什么需要copy,而不是retain呢!因为如果对myString赋值原字符串是一个可变的字符串(NSMutableString)对象的话,用retain的话,当原字符串改变的时候你的myString属性也会跟着变掉。我想你不希望看到这个现象。实际上博主测试,如果原来的字符串是NSString的话,也只是retain一下,并不会copy副本

@property (nonatomic, retain) UIView * myView;

这里定义了一个UIView类型的属性,不需要原子操作,所以用nonatomic.

当对myView 赋值的时候原来的UIView对象retainCount会加1

//接口文件

@interface MyClass : NSObject

@property (nonatomic, assign) int number;

@property (nonatomic, copy) NSString * myString;

@property (nonatomic, retain) UIView * myView;

@end

?

//实现文件

@implementation MyClass

@synthesize number;

@synthesize myString;

@synthesize myView;

//释放内存

-(void) dealloc

{

[myString release]; //copy的属性需要release;

[myView release]; //retain的属性需要release;

[super dealloc]; //传回父对象

}

@end

假如你有一段代码创建了一个MyClass对象

MyClass * instance = [MyClass alloc] init];

//number赋值,没什么可说的,简单数据类型就这样

instance.number = 1;

//创建一个可变字符串

NSMutableString * string = [NSMutableString stringWithString:@"hello"];

instance.myString = string; //myString赋值

[string appendString:@" world!"]; //string追加文本

NSLog(@”%@”,string); //此处string已经改变,输出为 “hello world!”

NSLog(@”%@”,instance.myString); //输出myString,你会发现此处输出仍然为 “hello”因为 myStringstring改变之前已经copy了一份副本

UIView * view = [[UIView alloc] init];

NSLog(@”retainCount = %d”,view.retainCount);

//输出view的引用计数,此时为1

instance.myView = view; //myView属性赋值

NSLog(@”retainCount = %d”,view.retainCount);

//再次输出view的引用计数, 此时为2,因为myViewview进行了一次retain

[view release];

//此处虽然viewrelease释放掉了,但myViewview进行了一次retain,那么myView保留的UIView的对象指针仍然有效。

[instance release] ;

// Setup two variables to point to the same string

NSString * str1 = @"Hello World";

NSString * str2 = str1;

// "Replace" the second string

str2 = @"Hello ikilimnik";

// And list their current values

NSLog(@"str1 = %@, str2 = %@", str1, str2);

output:str1 = Hello World, str2 = Hello ikilimnik

Mutable strings

// Setup two variables to point to the same string

NSMutableString * str1 = [NSMutableString stringWithString:@"Hello World"];

NSMutableString * str2 = str1;

// "Replace" the second string

[str2 setString:@"Hello ikilimnik"];

// And list their current values

NSLog(@"str1 = %@, str2 = %@", str1, str2);

output:str1 = Hello ikilimnik, str2 = Hello ikilimnik

注意,当你使用不可变的NSString class时,替换旧的字符串的唯一方式就是创建一个新的字符串然后更新你的变量“str2”

来指向这个新的字符串。这个操作不会影响“str1”所指向的内容,因此它将继续指向初始的字符串。

NSMutableString的例子里,我们没有创建第二个字符串,而是通过改变已经存在的可变字符串“str2”的内容来代替。

由于str1str2两个变量都仍然指向同一个字符串对象,从nslog中可以看到它们值都将会被更新。

理解指针变量和它实际指向对象的不同是非常重要的。一个NSString对象是不可变的,但是这并不阻止你改变指向这个不

可变对象的指针的值。

"NSString *"这个数据类型代表一个NSString对象的指针,不是NSString对象本身。

"NSMtableString *"这个数据类型则是代表"NSMutableString"对象本身,这两者是有区别的。

这也是有的时候我们使用NSMutableString类型字符串时,要使用copy的原因,因为可能不想改变新的字符串时影响到旧的字符串的值。

如:

NSMutableString * str2 = [str1 mutableCopy];

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font:11.0px Menlo}

Objective-C指针赋值时,retain count不会自动增加,需要手动retain

ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1

ClassA *obj2 = obj1; //retain count = 1

[obj2 retain]; //retain count = 2

[obj1 hello]; //输出hello

[obj1 release]; //retain count = 2 – 1 = 1

[obj2 hello]; //输出hello

[obj2 release]; //retain count = 0,对象被销毁

问题解决!注意,如果没有调用[obj2 release],这个对象的retain count始终为1,不会被销毁,内存泄露。

Objective-C中引入了autorelease pool(自动释放对象池),在遵守一些规则的情况下,可以自动释放对象。(autorelease pool依然不是.Net/Java那种全自动的垃圾回收机制

Objective-C的对象生成于堆之上,生成之后,需要一个指针来指向它。

ClassA *obj1 = [[ClassA alloc] init];

0 0