OC一些重要知识点<三>

常用的结构体

NSPoint和CGPoint

  • CGPoint和NSPoint是同义的
  • CGPoint代表的是二维平面中的一个点
    • 可以使用CGPointMake和NSMakePoint函数创建CGPoint

NSSize和CGSize

  • CGSize和NSSize是同义的
  • CGSize代表的是二维平面中的某个物体的尺寸(宽度和高度)
    • 可以使用CGSizeMake和NSMakeSize函数创建CGSize

NSRect和CGRect

  • CGRect和NSRect是同义的
  • CGRect代表的是二维平面中的某个物体的位置和尺寸
    • 可以使用CGRectMake和NSMakeRect函数创建CGRect

常见的结构体使用注意

  • 苹果官方推荐使用CG开头的:
    • CGPoint
    • CGSize

+ CGRect

NSNumber

1.NSNumber基本概念

  • NSArray\NSDictionary中只能存放OC对象,不能存放int\float\double等基本数据类

  • 如果真想把基本数据(比如int)放进数组或字典中,需要先将基本数据类型包装成OC对象

  • NSNumber可以将基本数据类型包装成对象,这样就可以间接将基本数据类型存进NSArray\NSDictionary中

2.NSNumber的创建

  • 以前

    • + (NSNumber *)numberWithInt:(int)value;
    • + (NSNumber *)numberWithDouble:(double)value;
    • + (NSNumber *)numberWithBool:(BOOL)value;
  • 现在

    • @10;
    • @10.5;
    • @YES;
    • @(num);

3.从NSNumber对象中的到基本类型数据

  • - (char)charValue;
  • - (int)intValue;
  • - (long)longValue;
  • - (double)doubleValue;
  • - (BOOL)boolValue;
  • - (NSString *)stringValue;
  • - (NSComparisonResult)compare:(NSNumber *)otherNumber;

- - (BOOL)isEqualToNumber:(NSNumber *)number;

NSValue基本概念

  • NSNumber是NSValue的子类, 但NSNumber只能包装数字类型

  • NSValue可以包装任意值

    • 因此, 可以用NSValue将结构体包装后,加入NSArray\NSDictionary中

常见结构体的包装

  • 为了方便 结构体 和NSValue的转换,Foundation提供了以下方法
  • 将结构体包装成NSValue对象

    • + (NSValue *)valueWithPoint:(NSPoint)point;
    • + (NSValue *)valueWithSize:(NSSize)size;
    • + (NSValue *)valueWithRect:(NSRect)rect;
  • 从NSValue对象取出之前包装的结构体

    • - (NSPoint)pointValue;
    • - (NSSize)sizeValue;
    • - (NSRect)rectValue;

任意数据的包装

  • NSValue提供了下列方法来包装任意数据

    • + (NSValue )valueWithBytes:(const void )value objCType:(const char *)type;
    • value参数 : 所包装数据的地址
    • type参数 : 用来描述这个数据类型的字符串, 用@encode指令来生成
  • 从NSValue中取出所包装的数据

    • - (void)getValue:(void *)value;

NSDate基本概念

  • NSDate可以用来表示时间, 可以进行一些常见的日期\时间处理

  • 一个NSDate对象就代表一个时间

  • [NSDate date]返回的就是当前时间

日期时间对象

  • 结合NSCalendar和NSDate能做更多的日期\时间处理

  • 获得NSCalendar对象


NSFileManager介绍

  • 什么是NSFileManager

    • 顾名思义, NSFileManager是用来管理文件系统的
    • 它可以用来进行常见的文件\文件夹操作
  • NSFileManager使用了单例模式

    • 使用defaultManager方法可以获得那个单例对象

集合对象的内存管理

  • 当一个对象加入到集合(数组)中,那么该对象的引用计数会+1
  • 当集合(数组)被销毁的时候,集合(数组)会向集合(数组)中的元素发送release消息
  • 集合(数组)增加一个对象的方法名称是addObject:

  • 当一个对象加入到集合中,那么该对象的引用计数会+1

  • 当把一个对象从集合中移除时,会向移除的元素发送release消息
  • 集合(数组)移除一个对象的方法名称是removeObject:

集合对象内存管理总结

  • 1.官方内存管理原则

    • 1> 当调用alloc、new、copy(mutableCopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease
    • 2> 当调用retain方法让对象的计数器+1,就必须在最后调用一次release或者autorelease
  • 2.集合的内存管理细节

    • 1> 当把一个对象添加到集合中时,这个对象会做了一次retain操作,计数器会+1
    • 2> 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1
    • 3> 当一个对象从集合中移除时,这个对象会一次release操作,计数器会-1
  • 3.普遍规律

    • 1> 如果方法名是add\insert开头,那么被添加的对象,计数器会+1
    • 2> 如果方法名是remove\delete开头,那么被移除的对象,计数器-1

copy基本概念

  • 什么是copy

    • Copy的字面意思是“复制”、“拷贝”,是一个产生副本的过程
  • 常见的复制有:文件复制

    • 作用:利用一个源文件产生一个副本文件
  • 特点:

    • 修改源文件的内容,不会影响副本文件
    • 修改副本文件的内容,不会影响源文件
  • OC中的copy

    • 作用:利用一个源对象产生一个副本对象
  • 特点:

    • 修改源对象的属性和行为,不会影响副本对象
    • 修改副本对象的属性和行为,不会影响源对象

Copy的使用

  • 如何使用copy功能

    • 一个对象可以调用copy或mutableCopy方法来创建一个副本对象
    • copy : 创建的是不可变副本(如NSString、NSArray、NSDictionary)
    • mutableCopy :创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
  • 使用copy功能的前提

    • copy : 需要遵守NSCopying协议,实现copyWithZone:方法
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
  • 使用mutableCopy的前提
    • 需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end

深复制和浅复制

  • 浅复制(浅拷贝,指针拷贝,shallow copy)
    • 源对象和副本对象是同一个对象
    • 源对象(副本对象)引用计数器+1,相当于做一次retain操作
    • 本质是:没有产生新的对象
    NSString *srcStr = @"lnj";
    NSString *copyStr = [srcStr copy];
    NSLog(@"src = %p, copy = %p", srcStr, copyStr);
  • 深复制(深拷贝,内容拷贝,deep copy)
    • 源对象和副本对象是不同的两个对象
    • 源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
    • 本质是:产生了新的对象
    NSString *srcStr = @"lnj";
    NSMutableString *copyStr = [srcStr mutableCopy];
    NSLog(@"src = %p, copy = %p", srcStr, copyStr);
    NSLog(@"src = %@, copy = %@", srcStr, copyStr);
    [copyStr appendString:@" cool"];
    NSLog(@"src = %@, copy = %@", srcStr, copyStr);
    NSMutableString *srcStr = [NSMutableString stringWithFormat:@"lnj"];
    NSString *copyStr = [srcStr copy];
    [srcStr appendString:@" cool"];
    NSLog(@"src = %p, copy = %p", srcStr, copyStr);
    NSLog(@"src = %@, copy = %@", srcStr, copyStr);
    NSMutableString *srcStr = [NSMutableString stringWithFormat:@"lnj"];
    NSMutableString *copyStr = [srcStr mutableCopy];
    [srcStr appendString:@" cool"];
    [copyStr appendString:@" 520it"];
    NSLog(@"src = %p, copy = %p", srcStr, copyStr);
    NSLog(@"src = %@, copy = %@", srcStr, copyStr);
  • 只有源对象和副本对象都不可变时,才是浅复制,其它都是深复制

copy与内存管理

  • 浅拷贝
    • 原对象引用计数器+1
    • 必须对原对象进行释放
    • 浅拷贝产生的副本对象和原对象是同一个对象
    char *cstr = "this is a c string";
    NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
    NSLog(@"str = %lu", [str1 retainCount]);
    NSString *str2 = [str1 copy];
    NSLog(@"str = %lu", [str1 retainCount]);
       [str2 release];必须做一次release //浅拷贝产生的副本对象和原对象是同一个对象
  • 深拷贝
    • 必须释放新对象
    • 深拷贝是产生了新的对象
    char *cstr = "this is a c string";
    NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
    NSLog(@"str = %lu", [str1 retainCount]);
    NSMutableString *str2 = [str1 mutableCopy];
    NSLog(@"str = %lu", [str1 retainCount]);
    [str2 release]; // 必须做一次release

@property中的copy的作用

  • 防止外界修改内部的值
    @interface Person : NSObject
    @property (nonatomic, retain) NSString *name;
    @end
    NSMutableString *str = [NSMutableString stringWithFormat:@"lnj"];

    Person *p = [[Person alloc] init];
    p.name = str;
    // person中的属性会被修改
    [str appendString:@" cool"];
    NSLog(@"name = %@", p.name);
  • 防止访问对象对象已经释放

  • 不用copy情况

    Person *p = [[Person alloc] init];
    p.name = @"lnj";
    Dog *d = [[Dog alloc] init];
    d.age = 10;
    NSLog(@"retainCount = %lu", [d retainCount]); // 1
    p.pBlock = ^{
        // 报错, 调用之前就销毁了
        NSLog(@"age = %d", d.age);
    };
    [d release]; // 0
    p.pBlock();
    [p release];
  • 用copy情况
    Person *p = [[Person alloc] init];
    p.name = @"lnj";
    Dog *d = [[Dog alloc] init];
    d.age = 10;
    NSLog(@"retainCount = %lu", [d retainCount]); // 1
    p.pBlock = ^{
        // 会对使用到的外界对象进行一次retain
        NSLog(@"age = %d", d.age);
        NSLog(@"retainCount = %lu", [d retainCount]); // 1
    };
    [d release]; // 1
    p.pBlock();
    [p release];

@property内存管理策略选择

  • 非ARC

    • 1> copy : 只用于NSString\block
    • 2> retain : 除NSString\block以外的OC对象
    • 3> assign :基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign
  • ARC

    • 1> copy : 只用于NSString\block
    • 2> strong : 除NSString\block以外的OC对象
    • 3> weak : 当2个对象相互引用,一端用strong,一端用weak

+ 4> assgin : 基本数据类型、枚举、结构体(非OC对象)

// MRC, A对象想拥有B对象, 需要对B对象进行一次retain
//      A对象不用B对象了, 需要对B对象进行一次release
//      property的时候进行retain, dealloc的时候进行release

// ARC, A对象想拥有B对象, 那么就需要用一个强指针指向B对象
//      A对象不用B对象了, 什么都不需要做, 编译器会自动帮我们做

// 在ARC中保存一个对象用strong, 相当于MRC中的retain

        @property(nonatomic, strong)Dog *dog;

自定义类实现copy操作

  • 让类遵守NSCopying协议
  • 实现 copyWithZone:方法,在该方法中返回一个对象的副本即可。
  • 在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致, 并返回该对象.

    • >zone: 表示空间,分配对象是需要内存空间的,如果指定了zone,就可以指定 新建对象对应的内存空间。但是:zone是一个非常古老的技术,为了避免在堆中出现内存碎片而使用的。在今天的开发中,zone几乎可以忽略
  • 无父类实现

-(id)copyWithZone(NSZone *)zone{

   CustomMode *custom = [[[self class]  copyWithZone:zone]  init];

   Custom ->_a = [_a copyWithZone:zone];

   Custom -> _c = _c;//不是对象的 直接赋值

   Return custom;

}
  • 有父类实现
    • 不调用父类方法, 无法拷贝父类中继承的属性
    • 不重新父类copyWithZone, 无法拷贝本来中的特有属性
-(id)copyWithZone(NSZone *)zone{

    CustomModel *custom = [super copyWithZone:zone];
    ….
    Return custom;
}

单例模式概念

  • 什么是单例模式:(Singleton)

    • 类的对象成为系统中唯一的实例,提供一个访问点,供客户类 共享资源单例就是无论怎么创建都只能有一个实例对象
  • 什么情况下使用单例?

    • 1、类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方 法。
    • 2、这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
  • 创建单例对象的方法一般以什么开头?

    • 1.一般情况下创建一个单例对象都有一个与之对应的类方法
    • 2.一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头

单例宏抽取

  • 单例通过宏定义的方式提取,主要目的是为了方便调用复杂的单例模式的代码,单例宏提取分为MRC和ARC两种模式下的提取,这两种模式下的提取是有区别的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值