Objective-C 学习笔记

超类

即父类,通过 [super setName: @"a"] 可以调用超类方法

复合

是指一个对象由其他多个对象组成

对象初始化

@interface Car : NSObject
(
  Engine *engine;
)
@end

@implementation Car
- (id) init
{
  //因init方法可能返回不同的对象,所以需要更新self。如从很长的字符串生成新字符串,初始化函数可能创建属于其他类的对象,类似NSCFArray问题。实例变量的内存位置到隐藏self参数之间的距离是固定的,所以得保证init返回的对象,在后面引用能够正确映射内存位置。   
if(self = [super init]){     engine = [Engine new];   }   return (self); } //init @end

若要超类可以完成所需的一次性初始化,需要调用[super init]。将[super init]的结果赋给self是oc的标准惯例。防止超类在初始化过程中返回的对象不同于原先创建的对象。

 Car *car = [[Car alloc] init]  alloc先分配内存空间,并且内存初始化为0,指针为nil;init初始化对象。

new 和 alloc init可以说等价,但一般不用

#import

1、导入系统头文件用 <>,导入项目本地头文件用 ""

2、a.m 的implementation 时需要 #import "a.h" 

3、@interface中, a.m 可以使用 @class Engine 来告诉编译器以后会知道这是个什么,implementation中还是需要#import。#import会告诉编译器类的详细信息,而@class只会告知这是一个类。#import循环依赖引用会报错,而@class不会, A引用B,B引用A。不可以在子类里使用@class引用超类,因为那时候编译器还不知道超类的信息。

 

内存管理

alloc、new、copy都会使引用计数+1

Mango *mango = [Mango new];  //count1
[mango retain];  //count 2
[mango release]; //count 1
[mango release];  // dealloc   count1
//dealloc 后引用计数不一定是0,因为虽然对象已经销毁,但是实际内存里的数据并没有删除

 

访问器

@property @synthesize  编译器自动生成get、set方法,不用成对出现

@synthesize (readwrite/readonly copy/retain) NSString *name;

1、readwrite 可读写,默认

2、readonly 只读,只可调用get方法

3、copy 复制对象

4、retain 保留和释放操作

5、copy/retain不指定则 赋值操作

 

类别

类别类似C#的扩展方法,方法可以不实现,编译器不会抱错,所以调用之前最好先检查是否已实现。

@interface NSString (NumberConvenience类别名)

- (NSNumber *) lengthAsNumber类别方法;

@end

@implementation NSString (NumberConvenience)

- (NSNumber *) lengthAsNumber{

  unsigned int length = [self length];

  return ([NSNumber numberWithUnsignedInt: length]);

}

@end

调用 NSNumber *length = [@"abc" lengthAsNumber];

 

类扩展

 为一个类添加额外的原来没有的变量、方法或者合成属性。

@interface MyClass () { //类扩展    
    float value;    
}    
- (void)setValue:(float)newValue;    
@end   

 类别与类扩展的区别:

①类别中只能增加方法;

②是的,你没看错,类扩展不仅可以增加方法,还可以增加实例变量(或者合成属性),只是该实例变量默认是@private类型的(作用范围只能在自身类,而不是子类或其他地方);

③类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。

④类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。

⑤定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。

协议

1、非正式协议其实是NSObject(子类)的一个类别,可选实现

选择器@selector(方法) 和 obj respondToSelector:@Selector(方法) 能检测对象是否支持此方法

2、正式协议 @protocol 

  协议要求采用者必须实现列出的方法,不引入实例变量。2.0之前必须全部实现,2.0加入了 @required  @optional 可选和必选

@protocol NSCopying  //由cocoa声明

-(id) copyWithZone: (NSZone *) zone;

@end

@interface Engine : NSObject<NSCopying>

//instance variables

@end

@implementation Engine
-(id) copyWithZone: (NSZone *)zone
{
    //[self class] 保证调用对象不管是父类还是子类都可以被复制不出错
    Engine *engineCopy = [[[self class] allocWithZone: zone] init];
    return engineCopy;
}
@end

@interface Tire : NSObject<NSCopying>
{
   float pressure;
   float treadDepth;  
}
//...methods
@end
实现
-(id) copyWithZone: (NSZone *) zone
{
   Tire *tireCopy = [[[self class] allocWithZone:zone]
                                      initWithPressure: pressure
                                      treadDepth: treadDepth];
   return tireCopy;
}
Tire的子类AllWeatherRadial不需要<NSCopying>,因为继承了父类的NSCopying
@interface AllWeatherRadial : Tire
{
    float rainHandling;
    float snowHandling;
}
//... methods
@end
实现
-(id) copyWithZone: (NSZone *) zone
{
    //子类只需调用父类已实现的copy方法来复制自身,父类使用的self class保证复制的是自己
    AllWeatherRadial *tireCopy = [super copyWithZone: zone];
    [tireCopy setRainHandling: rainHandling];
    [tireCopy setSnowHandling: snowHandling];

    return tireCopy;
}

 -(void) setObjectValue: (id<NSCopying>) obj;   id<协议> 表示可以使用任意数据类型赋值,只要它实现了NSCopying协议

 

KVC 键值编码

-valueForKey:   -setValue:forKey:

如:NSNumber *number = [tire valueForKey:@"pressure"];

     [tire setValue: [NSNumber numberWithFloat: 12.0] forKey:@"pressure"];

kvc还可以使用路径调用

  NSNumber *level = [member valueForKey:@"memberExten.level"];

kvc可以进行一些计算返回

      NSNumber *count = [member valueForKey:@"invests.@count"];   计算invest数组的数量

  NSNumber *count = [member valueForKey:@"invests.@sum.amount"]; 计算投资总金额

  NSNumber *count = [member valueForKey:@"invests.@max.amount"]; 计算最大投资额

  NSNumber *count = [member valueForKey:@"invests.@avg.amount"]; 计算平均投资额

  NSArray *loans = [member valueForKey:"@invests.distinctUnionOfObjects.loanId"]; 去重取出所有投标Id

  NSDictionary *memberValues = [member dictionaryWithValuesForKeys: [NSArray arrayWithObjects: @"RegName", @"RealName", @"MobilePhone", nil]];  取出三个字段的值

  NSDictionary *values = [member dictionaryWithValuesForKeys: [NSArray arrayWithObjects:@"RegName", @"RealName", nil]];    取出值

      NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:

                             @"Mango", @"RegName", [NSNumber numberWithInt:22], @"Age", nil];

      [member setValuesForKeysWithDictionary: dic];   设置值

如果对象没有对应的key,会放弃操作,并引发-setValue:forUndefinedKey:方法,可以重写此方法做一些相应处理,比如存储一个NSMutableDictionary,获取方法为-valueForUndefinedKey:

如果为NSDictionary/NSMutableDictionary setObject:forKey: 设置nil,会警告

如果为NSMutableDictionary setValue:forKey: 设置nil,会删除这个key

 

posted @ 2015-03-14 00:55  Mango_  阅读(156)  评论(0编辑  收藏  举报