IOS学习时的一些笔记(一)

来源:互联网 发布:重复犯错歌词 知乎 编辑:程序博客网 时间:2024/06/05 16:41

@符号表示将使用oc的特殊用法,比如@property @selector
1、大循环时候内存释放问题:
oc中,当较大循环,如1M次时。循环过程中内存占用会绝对增长,即使有自动释放也不会起作用,因为在自动释放不会在循环进行中执行,一定会在循环结束后才执行
如:
int i;
for(i=0;i<1000000;i++){
    id object = [somearray objectAtIndex:i];
    NSString *desc = [object description];
    //otherthings to do
    }
在这一百万次循环中,内存一直增加,直到循环结束,自动释放池被销毁时,才会自动释放对象;解决方法:
 NSAutoreleasePool *pool;
    pool= [NSAutoreleasePool alloc]init];
    int i;
   for(i=0;i<1000000;i++){
        id object = [somearray objectAtIndex:i];
        NSString *desc = [object description];
        //otherthings to do
    if(i%1000==0){//循环1000次进行一次销毁,并创建新的pool
        [pool release];
        pool =[[NSAutoreleasePool alloc]init];
        }
    }
[pool release];
//ps:自动释放池分配和销毁的操作代价很小,以至于可以每次循环都进行创建销毁操作;
2、启用ARC之后,通常的内存管理命令都成了空指令;iPhone开发不建议使用arc
3、oc中,初始化对象包括两步:分配(allocatin)和初始化(initialization),有别于java和c#
    初始化两种常用方法:[类名 new]和[[类名 alloc] init] ,cocoa中通常使用后者(不会使用后者的程序员才会使用前者,所以你懂的)
4、分配:执行从os中获取内存,指定用于存放对象的实例变量位置,并将内存区域全部初始化为0
    初始化:从os中取得内存,准备用于存储对象;
    类方法alloc对对象分配内存区域并清零该区域,实例方法init用于获得一个对象并使其运行;
5、使用if(self=[super init])的原因是初始化可能返回完全不一样的对象,
建议使用 if(self = [super init])类似这种方法
6、注意“惰性求值”
7、不是通过alloc、copy、new方法创建的对象它的保留计数器的值为1,而且可以认为是自动释放的,所以不用手动释放
8、使用set时候,最好使用“保留以前已传入的对象并释放当前对象”,例如:
-(void) setEngine:(Engine *) newEngine{
    [newEngine retain];//已传入的保留
    [engine release];//此处的engine是当前对象,释放掉
    engine = newEngine;//完成赋值
}//setEngine
9、指定初始化函数:该类的所有初始化方法使用指定初始化函数进行初始化操作,子类使用其超类的指定初始化函数进行超类的初始化,通常使用接受参数最多的初始化方法成为指定初始化函数,其他则使用类似指定初始化函数的形式。(在初始化函数不止一个的时候需要指定初始化函数)
10、特性property:@property 表示声明了一个新对象的属性,自动声明该属性的seter和getter
11、@synthesize 表示创建该属性的访问器,当遇到@synthesize someProper; 的时候,编译器会输出-setSomeProper和-someProper方法已编译代码(即setter和getter方法)
12、点表达式:oc2.0之后可以使用类似c++和java的点,如
[tire setRainHandling:20+i];
可以写作:tire.rainHandling=20+i;
点表达式出现在等号左边,自动调用setter方法,在右边自动调用Getter方法,即点表达式是调用访问器的一种快捷方式
 
13、需要执行copy操作对某属性赋值,则在@property的时候需要声明copy属性,同理,若某对象需要保留,则声明(retain),(nonatomic则是不在多线程使用,可以提升速度,尤其是iphone中),如果不希望保留属性对象,可以使用assign方法避免保留周期问题,声明readonly则只生成getter方法,
 
14、self在oc中的应用:self.name用来消除歧义,表示期望使用访问器访问name
 
15,category类别:@interface NSString(someFun)
@end//.h文件
 
@implenmentation NSString (someFun)
@end//.m文件
16、使用类别可以将单个较大的类以某种条件分为多个小类
eg:
@interface CategorySamp : NSObject     {
    int samp1;
    int samp2;
    int samp3;
}
@end //
 
@interface Category(Samp1){   
    -(void) setSamp1:(int) samp1;
    -(int) samp1;
}
@end//
 
@interface Category(Samp2){
    -(void) setSamp2:(int) samp2;
    -(int) samp2;
}
@end//
 
@interface Category(Samp3){
    -(void) setSamp1:(int) samp3;
    -(int) samp3;
}
@end//
 
 
#import "CategorySamp.h"
 
@implementation CategorySamp
 
-(NSString *)describtion{
    NSString *desc;
    desc=[NSString stringWithFormat:@"%d %d %d",samp1,samp2 ,samp3];
    return(desc);
}
@end
 
还需要在对应的.m文件中添加响应的处理,此处省略
 
 
17、非正式协议和委托类别:委托:是一种对象,另一个类的对象要求委托对象执行他的某些操作
 
18、正式协议:一个命名的方法列表 ,需要显式的在类的@interface中列出协议的名称,这样才表名该类遵守该协议,且需要实现该协议的所有方法,sample code:
@protocol SampleProtocol
@required//后接必须要实现的
@optional//后接可选的,不一定要实现,
//...
@end
 
引用时 @interface SampClass:NSObject<SampleProrocol>...
 
19.复制 copy :浅层复制(Shallow Copy)不复制引用对象,新复制的对象只指向现有的引用对象;深层复制(deep copy)将复制所有的引用对象
 
20、plist 属性列表包括:NSArray,NSDictionary,NSString,NSNumber,NSDate,NSData及它们的变体(ifexists)
 
21、通过KVC,可以获取不存在getter和setter方法的对象值,无需通过对象指针直接访问实例变量,即通过setValue和valueForKey,
 
22、NSPredicate 指定过滤条件,类似sql中的where,使用此类可以省去很多不必要的循环等操作,sampleCode :NSArray *array =[ [ NSArray alloc] initWithObjects: @"f1",@"f2",@"f3",@"s1",nil];
                                            NSString *str = @"f";
                                            NSPredicate *predicate = [NSPredicateWithFormat:@"SELF CONTAINS %@",str];
                                        NSLog("after predicate:%@",[array, filteredArrayUsingPredicate:predicate];
除了过滤Array,还能对字符串首字母判断,字符替换,截取字符串,判断手机号码,邮箱验证NSDate筛选等诸多操作,详见http://blog.csdn.net/ztp800201/article/details/8116081;
(SELF CONTAINS 是字符串比较操作符,不是集合操作符)
 
23、通常的引用有两种方法: 1. 通过#import  2.通过@class
前者方式会包含被引用类的所有信息,包括被引用类的变量和方法,后者只是告诉编译器在A.h中 B *b只是类的声明,如果需要引用这个类的实体变量或者方法,还是需要import;@class可以处理互相引用而导致死循环问题, 多层@import极度耗费时间,大型软件中需要减少.h文件的include。
当A.h中仅需要声明一个B的指针时候,在A.h中声明  @B
                                                                                    B *b;
 
使用原则: 头文件只import超类,消息文件里面import需要发消息过去的类,其他地方就用@class转向声明
 
24、真机调试时,Entitlements.plist中添加的get-task-allow如果没勾选,也有可能导致提示证书无效无法真机调试,这个原因待查证。
--------------------------------------------分割线-----内存管理专题-------------------------------
25、自动释放池中如果有大量的autorelease,则需要注意控制数量,因为在如果自动释放池没有销毁,这部分都将保留,等到pool销毁的时候再销毁,很容易导致内存不足,如sample Code:

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

int i, j;

for (i = 0; i < 100; i++ )

{

 for (j = 0; j < 100000; j++ )

    [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。

}

[pool release];

return (0);

} // main

 
26、除了allocnewcopy之外的方法创建的对象都被声明了autorelease,release一个空指针是合法的,但是不会发生任何事
 
27、OC的对象生成于堆之上,生成后需要一个指针来指向:ClassA *obj1=[[ClassA alloc]init];
    OC中的ref count或者retain count表示对象被引用的次数:即,如果被两个指针指向,则count为2
需要销毁的时候调用release,则减1,为0时才会调用dealloc真正销毁该对象

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

ClassA *obj2 = obj1; //retain count = 1//注意为何此处的count为1,因为该指针指向的obj1,而

                                                                //不是指向生成的对象

[obj1 hello]; //输出hello

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

[obj2 hello];

[obj2 release];

         [obj1 release]之后,obj2依然是个无效指针,处理类似问题的方式如下:ClassA *obj2 = obj1; 后面加上  [obj2 retain];//使count+1,(虽然能解决此问题,但是略麻烦,更简单的方法见下:)

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

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

[obj2 retain]; //retain count = 2

[obj1 hello]; //输出hello

//对于obj1,无需调用(实际上不能调用)release

[obj2 hello]; //输出hello

[obj2 release]; //retain count = 2-1 = 1//问题:为何此时的count依然为1,如何销毁?因为对象是使用autorelease标记过的,被记录入释放池中,会被记录池清理

 

    自动释放池中大规模循环释放的示例:

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

int i, j;

for (i = 0; i < 100; i++ )

{

 NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];

 for (j = 0; j < 100000; j++ )

    [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。

 [loopPool release];

}

[pool release];

return (0);

} // main

 
28、retain,谁release,谁创建,谁释放:只要你调用了retain,无论这个对象是如何生成的,你都要调用release
29、释放模版:1.release一个对象后,立即把指针清空:[obj1 release]; obj1=nil;
                    2.指针赋值给另一个指针:
    ClassA *obj2=obj1;                                          
    [obj2 retain];
    //todo something
    [obj2 release];
    obj2=nil;
                3.在一个函数中创建并返回对象,需要把这个对象设置为autorelease
    ClassA *Func1(){
        ClassA *obj=[[[ClassA alloc]init]autorelease];
        return obj;
    }
                            4.在子类的dealloc方法中调用基类的dealloc方法
    -(void)dealloc{
        ...
        [super dealloc];
    }
                5.
 
0 0
原创粉丝点击