Objective C类方法loaD和C有什么区别initialize的区别

ios开发中类方法与self的注意点 与实例方法区别
Objective-C里面既有实例方法也类方法。类方法(Class Method) 有时被称为工厂方法(Factory Method)或者方便方法(Convenience method)。工厂方法的称谓明显和一般意义上的工厂方法不同,从本质上来说,类方法可以独立于对象而执行,所以在其他的语言里面类方法有的时候被称为静态方法。
注意点一:类方法
1,类方法可以调用类方法。
2,类方法不可以调用实例方法,但是类方法可以通过创建对象来访问实例方法。
3,类方法不可以使用实例变量。类方法可以使用self,因为self不是实例变量。
4,类方法作为消息,可以被发送到类或者对象里面去(实际上,就是可以通过类或者对象调用类方法的意思)。
注意点二:self的规则
大家需要记住下面的规则:
1,实例方法里面的self,是对象的首地址。
2,类方法里面的self,是Class.
尽管在同一个类里面的使用self,但是self却有着不同的解读。在类方法里面的self,可以翻译成class self;在实例方法里面的self,应该被翻译成为object self。在类方法里面的self和实例方法里面的self有着本质上的不同,尽管他们的名字都叫self。
类方法创造的对象要不要用release释放?
答 不需要 这个对象被放到自动释放池中
Object-C中的私有方法和私有成员变量
成员变量默认对内是共有的,对外是私有的。
@interface Controller : NSObject
@private:
NSString *
+ (void)thisIsAStaticM
- (void)thisIsAnInstanceM
@interface Controller (Private)
- (void)thisIsAPrivateM
下面的代码就是怎样获取私有变量(记得加头文件#import ):
NSString *
Mobj *obj = [[Mobj alloc] init];
object_getInstanceVariable(obj, "mt_", (void *)&str);
NSLog(@"%@",str);
[obj release];
//===================================
实例方法和类方法的区别
类方法和实例方法
1:实例方法是— 类开头是+ 实例方法是用实例对象访问,类方法的对象是类而不是实例,通常创建对象或者工具类。
在实例方法里,根据继承原理发送消息给self和super其实都是发送给self
在类方法里面self是其他的类的类方法,在类方法中给self发送消息只能发类方法self是类super也是
什么时候用类方法,要创建一个实例时候获取一个共享实例,或者获取关于类的一些共有信息
类方法(class method)和实例方法(instance method)。类方法被限定在类范围内,不能被类的实例调用(即脱离实例运行)。alloc就是一种类方法。实例方法限定在对象实例的范围内(即实例化之前不能运行)。init就是一种实例方法,被alloc方法返回的对象实例调用。
NSObject *
object1 = [[NSObject alloc]
instance method
以减号 "-"
class method
以加号 “+” 开头,相当于static方法
3:see see 更健康
Objective-C
1.OC是一门基于C的面向对象语言,是C语言的一个超集,同时具有C语言的特征
2.OC对类的定义和实现以及初始化
//声明类接口,继承NSObject对象(该对象是OC中所有类的顶级父类,所有类都继承于它)
@interface ClassName :NSObject
//成员属性和成员函数的声明
+(void)function;//类方法,不需要实例化对象就可以调用的方法
- (void)function2 :(NSString *)arg;//成员方法,必须通过实例化的对象调用
@imlementation ClassName
//成员属性初始化和方法的定义
对象的初始化:ClassName *obj = [[ClassName alloc] init]
OC中以消息机制传递信息,发送alloc消息给类分配内存空间,发送init消息生成对象,指针指向对象本身。
3.类方法的调用
[obj function];
NSString *str = [NSString stringWithString:@"hello"];
[obj function2 : str];
4.输出函数
根据不同的输出格式输出不同的值 (%d :整形 ,%@:对象,%s:字符串)
NSlog(@“The result is %d”,intNum);
CF代表Core Foundation (Cocoa)
CFShow发送description给它显示的对象,CFShow打印的信息不会显示时间戳,NSLog会显示,同时CFShow不需要格式字符
串,它只能用于对象
CFShow(obj);
支持点表示法:myTableViewCell.textLabel.text = @"hello" 等价于 [[myTableViewCell textLabel] setText:@"hello"];
使用属性生成器 property
在h文件中声明: @property int year
在m文件中合成生成器:@synthesize year
使用 obj.year = 1999 相当于调用了 [obj setYear:1999];
可以自定义取值方法和赋值方法(getter and setter)
-(int)year
- (void) setYear : (int) newYear
//此处添加了一些基本的内存管理方法,保留新的值,释放以前的值
if(newYear != year)
[year release];
year = [newYear retain];
也可以绕过oc的命名约定,自己指定getter和setter方法的名称;
@property(getter = isExist,setter = setExist:) BOOL
使用过程中既可以使用新定义的方法名,也可以使用以前的方法(点表示法)
属性的特性:readwrite readonly assign retain copy nonatomic
assign:默认行为,使用@property int year就使用了assign行为,就是给实例变量赋了一个值
retain:实现了两个功能,一个是保留了赋值时传递的对象,其次是赋值前释放了以前值,使用retain可以实现上面讨论的内存管理的优点,使用时加上 @property (retain)int year;
copy:发送一条复制的消息给被传递的对象,保留它,并释放任何以前的值;
nonactomic:非原子访问器,加上后可以提升访问速度,但当两个线程同时修改同一个属性时就会出现问题,原子属性可以保证属性在被一个线程使用时不被另一个线程访问,不存在atomic关键字,默认情况下,所有方法都是自动合成的。(类似与java中的线程锁机制synchronized)
readwrite:可读写
readonly:只读面试那些事儿
过去两个星期里,为了完成一个工作,接触到了NSObject中非常特别。它们的特别之处,在于iOS会在运行期提前并且自动调用这两个方法,而且很多对于类方法的规则(比如继承,)都有不同的处理。
而因为这两个方法是在程序运行一开始就被调用的方法,我们可以利用他们在类被使用前,做一些预处理工作。比如我碰到的就是让类自动将自身类名保存到一个NSDictionary中。
先来看看里对这两个方法说明:
The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s +load method is called after all of its superclasses’ +load methods.
A category +load method is called after the class’s own +load method.
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
Apple的文档很清楚地说明了initialize和load的区别在于:load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。
它们的相同点在于:方法只会被调用一次。(其实这是相对runtime来说的,后边会做进一步解释)。
文档也明确阐述了方法调用的顺序:父类(Superclass)的方法优先于子类(Subclass)的方法,类中的方法优先于类别(Category)中的方法。
不过还有很多地方是文章中没有解释详细的。所以再来看一些示例代码来明确其中应该注意的细节。
+(void)load与+(void)initialize初探
1 +(void)load会引发+(void)initialize
2 /******* Interface *******/
3 @interface SuperClass : NSObject
6 @interface ChildClass : SuperClass
9 @interface Insideinitialize : NSObject
10 - (void)objectM
13 /******* Implementation *******/
14 @implementation SuperClass
16 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
20 + (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
26 @implementation ChildClass
28 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
Insideinitialize * obj = [[Insideinitialize alloc] init];
[obj objectMethod];
[obj release];
37 @implementation Insideinitialize
39 - (void)objectMethod {
NSLog(@"%@ %s", [self class], __FUNCTION__);
43 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
47 + (void) load {
NSLog(@"%s", __FUNCTION__);
这个示例代码中,一个SuperClass实现了+(void)load和+(void)initialize方法(实际上应该算是重写覆盖了NSObject的这两个方法);ChildClass继承于SuperClass,但是只重写+(void)initialize没有+(void)load;Insideinitialize类也有+(void)load和+(void)initialize方法,它在ChildClass的i+(void)initialize方法中被构建出一个对象。类中的每个函数的实现都非常简单,只是输出类名和方法名。除了Insideinitialize的+(void)load方法只输出了类名,没有使用[self class]。
首先我们在Xcode的项目中只简单import这些类,而不去使用他们的,然后运行项目就会得到下边的结果:
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
Insideinitialize +[Insideinitialize load]
就像Apple的文档中说的一下,只要有引用runtime就会自动去调用类的+(void)load方法。不过从输出中,我们还发现SuperClass的+(void)initialize也被调用了,而且是在+(void)load之前被执行;而Insideinitialize的+(void)initialize并没有执行。这是因为在SuperClass的+(void)load方法中,我们调用了类的class方法([self class]),这就符合文档中对+(void)initialize的说明:在类的第一个方法被调用前调用。同时也说明runtime对+(void)load的调用并不视为类的第一个方法。而ChildClass因为没有用到,所以+(void)initialize的方法被没有被执行,而且它也没有去执行父类的+(void)load方法(虽然它有继承下该方法)。
+(void)load和+(void)initialize可当做普通类方法(Class Method)被调用
接着, 在程序中让ChildClass直接调用load:
[ChildClass load];
程序正常运行,并输出了结果:
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
+[Insideinitialize load]
ChildClass +[ChildClass initialize]
Insideinitialize +[Insideinitialize initialize]
Insideinitialize -[Insideinitialize objectMethod]
ChildClass +[SuperClass load]
前面三个结果跟之前一样,不过之后ChildClass的+(void)initialize也被自动执行调用,并且我们可以在其中安全创建出Insideinitialize类并使用它,而Insideinitialize因为调用alloc方法是第一次使用类方法, 所以激发了Insideinitialize的+(void)initialize。
另一个方面,ChildClass继承下了+(void)load而且可以被安全地当做普通被使用。这也就是我之前所说的load和initialize被调用一次是相对runtime而言(比如SuperClass的initialize不会因为自身load方法调用一次,又因为子类调用了load又执行一次),我们依然可以直接去反复调用这些方法。
子类会调用父类的+(void)initialize
接下来,我们再修改一下SuperClass和ChildClass:去掉SuperClass中的+(void)load方法;让ChildClass来重写+(void)load,但是去掉+(void)initialize。
1 /******* Interface *******/
2 @interface SuperClass : NSObject
5 @interface ChildClass : SuperClass
8 @interface Insideinitialize : NSObject
9 - (void)objectM
12 /******* Implementation *******/
13 @implementation SuperClass
15 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
21 @implementation ChildClass
23 + (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
依然还是简单的引入这些类,并不去使用它们。运行之后,我们会得到这样的结果:
SuperClass +[SuperClass initialize]
ChildClass +[SuperClass initialize]
ChildClass +[ChildClass load]
和之前一样,+(void)load会引起+(void)initialize。也很Apple文档中讲得那样,子类方法的调用会激起父类的+(void)initialize被执行。不过我们也看到虽然ChildClass没有定义+(void)initialize,但是它会使用父类的+(void)initialize。而之前的示例,我们看到子类并不会在runtime时去使用父类的+(void)load,也就是说只有新定义的+(void)load才会被runtime去调用执行。
类别(Category)中的+(void)load的+(void)initialize
我们再来看看类和类的中+(void)load和+(void)initialize的区别。
1 /******* Interface *******/
2 @interface MainClass : NSObject
5 /******* Category Implementation *******/
6 @implementation MainClass(Category)
8 + (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
12 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
18 @implementation MainClass(OtherCategory)
20 + (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
24 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
30 /******* Implementation *******/
31 @implementation MainClass
33 + (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
37 + (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
简单import,运行,我们看到的结果是:
MainClass +[MainClass(OtherCategory) initialize]
MainClass +[MainClass load]
MainClass +[MainClass(Category) load]
MainClass +[MainClass(OtherCategory) load]
同样的+(void)initialize优先于+(void)load先执行。但是很明显的不同在于,只有最后一个的+(void)initialize执行,其他两个都被隐藏。而对于+(void)load,三个都执行,并且如果Apple的文档中介绍顺序一样:先执行类自身的实现,再执行中的实现。
最后再来看一个示例
1 @interface MainClass : NSObject
4 @implementation MainClass
6 + (void) load {
NSArray *array = [NSArray array];
NSLog(@"%@ %s", array, __FUNCTION__);
运行这段代码,Xcode给出如下的信息:
objc[84934]: Object 0x10a512930 of class __NSArrayI autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
18:07:39.042 ClassMethod[] (
) +[MainClass load]
其原因是runtime调用+(void)load的时候,程序还没有建立其autorelease pool,所以那些会需要使用到autorelease pool的代码,都会出现异常。这一点是非常需要注意的,也就是说放在+(void)load中的对象都应该是出来并且不能使用来释放。
不需要显示使用super调用父类中的方法
当我们定义-(id)init和-(void)dealloc方法时,我们总是需要使用super关键字来调用父类的方法,让父类也完成相同的操作。这是因为对对象的初始化和销毁过程,Objective-C不像C++,C#那样会自动调用父类默认构造函数。因此我们总是需要将这两个函数写成这样:
1 - (id)init {
if ((self = [super init])) {
//do initialization
9 - (void)dealloc {
//do release
[super dealloc];
但是+(void)initialize和+(void)load不同,我们并不需要在这两个方法的实现中使用super调用父类的方法:
1 + (void)initialize {
//do initialization thing
[super initialize];
6 + (void) load {
//do some loading things
[super load];
super的方法会成功调用,但是这是多余的,因为runtime对自动对父类的+(void)load方法进行调用,而+(void)initialize则会随子类自动激发父类的方法(如Apple文档中所言)不需要显示调用。另一方面,如果父类中的方法用到的self(像示例中的方法),其指代的依然是类自身,而不是父类。
+(void)load
+(void)initialize
在程序运行后立即执行
在类的方法第一次被调时执行
若自身未定义,是否沿用父类的方法?
类别中的定义
全都执行,但后于类中的方法
覆盖类中的方法,只执行一个
References:
上一篇: 下一篇:
&div class="postDesc"&posted @ &span id="post-date"& 12:35&/span& &a href="/ider/"&Ider&/a& 阅读(&span id="post_view_count"&26613&/span&) 评论(&span id="post_comment_count"&11&/span&)
&a href="/EditPosts.aspx?postid=2708419" rel="nofollow"&编辑&/a& &a href="#" onclick="AddToWz(2708419);"&收藏&/a&&/div&
&script type="text/javascript"&var allowComments=true,cb_blogId=78869,cb_entryId=2708419,cb_blogApp=currentBlogApp,cb_blogUserGuid='0be76e0b-6d9b-de11-ba8f-001cf0cd104b',cb_entryCreatedDate=' 12:35:00';loadViewCount(cb_entryId);&/script&
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1462次
排名:千里之外
转载:21篇
(2)(2)(4)(21)(1)Powered by
| Copyright 2008 - 2014 by

我要回帖

更多关于 A和C区别 的文章

 

随机推荐