黑马程序员——ios开发基础之OC中Foundation框架(二)、copy以及单例

本文深入探讨了Objective-C的Foundation框架,包括其核心概念和使用。接着,详细讲解了`copy`关键字的工作原理及其在内存管理中的作用。最后,介绍了单例模式的实现和在iOS开发中的应用,帮助开发者更好地理解和运用这些关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

第一讲 Foundation框架(二)

1、NSFileManager介绍和用法
            顾名思义, NSFileManager是用来管理文件系统的
           它可以用来进行常见的文件\文件夹操作(拷贝、剪切、创建等)
            NSFileManager使用了单例模式singleton
            使用defaultManager方法可以获得那个单例对象
             [NSFileManager defaultManager]
           1)  NSFileManager文件访问
            - (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error;
                获得path这个文件\文件夹的属性
            - (NSArray *)subpathsAtPath:(NSString *)path;
                查找给定路径下的所有子路径,返回一个数组, 深度查找,不限于当前层,也会查找package的内容。
           - (NSArray *)subpathsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;
                获得path的所有子路径(后代路径),上面两个方法功能一样。
           - (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;
                获得path的当前子路径(path下的所有直接子内容,path必须是一个目录)
           - (NSData *)contentsAtPath:(NSString *)path;
                 获得文件内容
           2)NSFileManager文件操作
                 - (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)
                      createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error;
                       只能创建文件夹(createIntermediates为YES代表自动创建中间的文件夹)
                       注意如果要创建的目录已经存在,则本次创建失败
                -(BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError
                **)error;
                    拷贝,如果目标目录已经存在同名文件,则无法拷贝
              - (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError
              **)error;
                      移动(剪切)
              - (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
                       删除
              - (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data
                      attributes:(NSDictionary *)attr;
                          创建文件
                  (NSData是用来存储二进制字节数据的)
                    // 把字符串转换为NSData
                   NSString *s1 =@"hello”;
                NSData *data = [s1 dataUsingEncoding:NSUTF8StringEncoding];
2、常见结构体
          1) CGPoint和NSPoint是同义的
           typedef CGPoint NSPoint;
           CGPoint的定义
            struct CGPoint {
                CGFloat x;
                CGFloat y;
             };
           typedef struct CGPoint CGPoint;
           typedef double CGFloat; //64位是double, 32位是float
          CGPoint代表的是二维平面中的一个点
          可以使用CGPointMake和NSMakePoint函数创建CGPoint
         2)NSSize和CGSize的使用
              CGSize和NSSize是同义的
                 typedef CGSize NSSize;
                    CGSize的定义
                   struct CGSize {
                       CGFloat width;
                      CGFloat height;
                    };
             typedef struct CGSize CGSize;
          CGSize代表的是二维平面中的某个物体的尺寸(宽度和高度)
          可以使用CGSizeMake和NSMakeSize函数创建CGSize
         3)CGRect和NSRect是同义的
              typedef CGRect NSRect;
               CGRect的定义
                  struct {
                        CGPoint origin;
                       CGSize size;
                  };
              typedef struct CGRect CGRect;
          CGRect代表的是二维平面中的某个物体的位置和尺寸
          可以使用CGRectMake和NSMakeRect函数创建CGRect
3、NSNumber的使用
        NSArray\NSDictionary中只能存放OC对象, 不能存放int\float\double等基本数据类
        如果真想把基本数据(比如int)放进数组或字典中, 需要先将基本数据类型包装成OC对象
         NSNumber的创建
               以前的写法
               + (NSNumber *)numberWithInt:(int)value;
               + (NSNumber *)numberWithDouble:(double)value;
               + (NSNumber *)numberWithBool:(BOOL)value;
              现在的写法
                 @10;
                 @10.5;
                 @YES;
                 @(num); // 如果是变量必须加()
                 @这种写法,只能包装数字,返回值就是NSNumber *类型。
             从NSNumber对象中的到基本类型数据
               - (char)charValue;
               - (int)intValue;
               - (long)longValue;
               - (double)doubleValue;
               - (BOOL)boolValue;
               - (NSString *)stringValue;
               - (NSComparisonResult)compare:(NSNumber *)otherNumber;
               - (BOOL)isEqualToNumber:(NSNumber *)number;
4、NSValue的介绍和使用
             NSValue包装对象指针, CGRect结构体等 
    一个NSValue对象是用来存储一个C或者Objective-C数据的简单容器。它可以保存任意类型的数据,比如int, float, char,当然也可以是指pointers, structures, and object ids。 NSValue类的目标就是允许以上数据类型的数据结构能够被添加到集合里,例如那些需要其元素是对象的数据结构,如NSArray或者NSSet的实例。需要注意的是NSValue对象一直是不可枚举的。为了方便 结构体 和 NSValue 的转换, Foundation提供了以下方法
             将结构体包装成NSValue对象 -------> 存储结构体到集合中
              + (NSValue *)valueWithPoint:(NSPoint)point;
              + (NSValue *)valueWithSize:(NSSize)size;
              + (NSValue *)valueWithRect:(NSRect)rect;
            从NSValue对象取出之前包装的结构体
             - (NSPoint)pointValue;
             - (NSSize)sizeValue;
             - (NSRect)rectValue;
5、NSDate的介绍和使用
         NSDate可以用来表示时间, 可以进行一些常见的日期\时间处理一个NSDate对象就代表一个时间
            [NSDate date]返回的就是当前时间
              获取当前时区的时间
6、集合对象的内存管理
          当一个对象加入到集合中,那么该对象的引用计数会+1
          当集合被销毁的时候,集合会向集合中的元素发送release消息
           NSArray *arr = @[.........]; //会调用autolease方法
           NSArray *arr2 = [[NSArray alloc] init]; //需要我们手工 [arr release];
总结
          官方内存管理原则
          1> 当调用alloc、 new、 copy( mutableCopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease
          2> 当调用retain方法让对象的计数器+1,就必须在最后调用一次release或者autorelease
         集合的内存管理细节
          1> 当把一个对象添加到集合中时,这个对象会做了一次retain操作,计数器会+1
           2> 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1
           3> 当一个对象从集合中移除时,这个对象会一次release操作,计数器会-1
          普遍规律
           1> 如果方法名是add\insert开头,那么被添加的对象,计数器会+1
           2> 如果方法名是remove\delete开头,那么被移除的对象,计数器-1

第二讲   copy

1、 对象copy的概念
           Copy的字面意思是“复制”、“拷贝”,是一个产生副本的过程
           对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容。
           常见的复制有用一个源文件产生:文件复制
           作用:利一个副本文件
           1)特点:
                修改源文件的内容,不会影响副本文件
                修改副本文件的内容,不会影响源文件
               OC中的copy,就是指的对象的拷贝
               作用:利用一个源对象产生一个副本对象
               修改源对象的属性和行为,不会影响副本对象
               修改副本对象的属性和行为,不会影响源对象
           2)使用copy功能
               一个对象可以调用copy或mutableCopy方法来创建一个副本对象
                copy : 创建的是不可变副本(如NSString、 NSArray、 NSDictionary)
                mutableCopy :创建的是可变副本(如NSMutableString、 NSMutableArray、 NSMutableDictionary)
           3)使用copy功能的前提
                   copy : 需要遵守NSCopying协议,实现copyWithZone:方法
                        @protocol NSCopying
                            - (id)copyWithZone:(NSZone *)zone;
                        @end
                  mutableCopy : 需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
                     @protocol NSMutableCopying
                        -  (id)mutableCopyWithZone:(NSZone *)zone;
                    @end
           copy 就是浅复制,因为没有产生新的对象(有没有产生新的对象也是判断深浅复制的标准)
          mutableCopy 就是深复制,会再内存中重新分配一块内存空间
          4) copy与内存管理
                深复制(深拷贝,内容拷贝,deep copy)
                源对象和副本对象是不同的两个对象
                源对象引用计数器不变, 副本对象计数器为1(因为是新产生的)
                本质是:产生了新的对象
                 浅复制(浅拷贝,指针拷贝,shallow copy)
                  源对象和副本对象是同一个对象
                  源对象(副本对象)引用计数器 + 1, 相当于做一次retain操作
                 本质是:没有产生新的对象
2、@property内存管理策略的选择
             1.非ARC
                  1> copy : 只用于NSString\block
                  2> retain : 除NSString\block以外的OC对象
                  3> assign : 基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign
             2.ARC
                 1> copy : 只用于NSString\block
                 2> strong : 除NSString\block以外的OC对象
                 3> weak : 当2个对象相互引用,一端用strong,一端用weak
                 4> assgin : 基本数据类型、枚举、结构体(非OC对象)
3、自定义对象copy步骤
             新建Person类
           为Person类实现copy操作
              1)让Person类遵守NSCopying协议
              2)实现 copyWithZone: 方法, 在该方法中返回一个对象的副本即可。
              3)在copyWithZone方法中, 创建一个新的对象,并设置该对象的数据与现有对象一致,并返回该对象.
                      创建Person对象, 调用copy方法, 查看地址
            为Person类实现mutableCopy操作
             1)遵守NSMutableCopying协议
             2)实现协议对你的方法
- (id)mutableCopyWithZone:(NSZone *)zone{
      //创建对象
     Person *p1 = [[Person alloc] init];
    //用当前对象值给新对象的实例变量赋值
    p1.age = self.age;
    //返回新对象
    return p1;
}

第三讲  单例

1、单例模式:(Singleton)
            单例模式的意图是是的类的对象成为系统中唯一的实例,提供一个访问点,供客户类共享资源。
2、单例使用情景
           1)类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。
           2)这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
3、单例设计模式的要点:
            (1) 某个类只能有一个实例。
            (2)他必须自行创建这个对象
            (3)必须自行向整个系统提供这个实例;
            (4)为了保证实例的唯一性,我们必须将
                       -(id)copyWithZone:(NSZone *)zone
                      +(id)allocWithZone:(NSZone *)zone
                      -(id)retain
                      -(NSUInteger)retainCount
                     -(oneway void)release
                       -(id)autorelease 
                     的实现方法进行覆盖。
            (5)这个方法必须是一个静态类
4、在OC中实现单例模式:
            先创建一个单例类,即:
          #import <Foundation/Foundation.h>
                 @interface Bee : NSObject<NSCopying>//注意此处调用了NScoping协议
                     +(Bee *)shareIsrance;//此处定义了一个工厂方法,用工厂方法来限制实例化过程
                 @end //调用NScopying协议,从而在实现文件中覆盖
        单例模式实现
</pre><pre name="code" class="objc">Tools.h
#import <Foundation/Foundation.h>
@interface Tools : NSObject<NSCopying>
@property (nonatomic,assign) int num;
@property (nonatomic,copy) NSString *text;
+(instancetype)shareIntances;
@end
Tools.m
static Tools *instance = nil;
@implementation Tools
+(instancetype)shareIntances{
    if (instance==nil) {
     instance = [[self allocWithZone:NULL] init];
}
      return instance;
}
-(id)copyWithZone:(NSZone *)zone{
       return self;
}
+(id)allocWithZone:(NSZone *)zone{
@synchronized(self) {
      if (instance == nil) {
     instance = [super allocWithZone:zone];
      return instance;
  }
}
    return instance;
}
-(id)retain{
     return self;
} 
-(NSUInteger)retainCount{
      return NSUIntegerMax;
}
-(oneway void)release{

} 
-(id)autorelease{
     return self;
}
@end
         注意:所谓单例,即我们自己创建一个单例类,该类只能生成唯一的对象,即用 if (sharesingleton == nil) 方法来保证唯一性,为了防止该对象被复制( copy)或者retain 和 release 等操作,我们必须在所创建的单例的实现文件(.m 文件)中将父类的这些方法给覆盖,该目的是为了保证单例模式的一个严谨性。
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值