OC+5-Foundation续&copy&单例模式singleton

NSFileManger的介绍和用法(文件操作)

1、NSFileManager的介绍
     NSFileManager:用来管理文件系统的,进行常见的文件或文件夹操作(拷贝、剪切、创建等)
     NSFileManager使用了单例模式singleton,使用defaultManager方法可以获得那个单例对象

2、NSFileManager的基本使用(常见的判断)
      NSString *filePath = @"/Users/ZacharyUE/Desktop/str.plist;//先给一个路径
        NSString *filePath2 = @"/Users/ZacharyUE/Desktop";
       
//NSFileManager  用于判断
       
//创建文件管理对象,单例对象(在程序运行期间,只有一个对象存在)
       
NSFileManager *fm = [NSFileManager defaultManager];
       
//1)判断文件是否存在
       
BOOL isYES = [fm fileExistsAtPath:filePath];
       
NSLog(@"%d", isYES);
       
//2)判断是否是一个目录
       
if (isYES) {
           
BOOL isDir;
            [fm
fileExistsAtPath:filePath2 isDirectory:&isDir];
           
if (isDir) {
               
NSLog(@"这是一个目录");
            }
else {
               
NSLog(@"不是一个目录");
            }
        }
       
//3)判断文件是否可读
        isYES = [fm
isReadableFileAtPath:filePath];
       
NSLog(@"%d", isYES);
       
//4)是否可写
        isYES = [fm
isWritableFileAtPath:filePath2];
       
NSLog(@"%d", isYES);
       
//5)是否可删除
        isYES = [fm
isDeletableFileAtPath:filePath];
        NSLog(@"%d", isYES);


3、NSFileManager用法深入1
     -NSFileManager的文件访问
       //创建文件对象
        NSFileManager *fm = [NSFileManager defaultManager];
        NSString *filePath = @"/Users/ZacharyUE/Desktop/str.plist;    //文件路径
        NSString *dirPath = @"/Users/ZacharyUE/Desktop/儒释道;         //目录路径
        //1)何如获取文件的信息(属性)
       
NSDictionary *dic = [fm attributesOfItemAtPath:filePath error:nil];
       
NSLog(@"%@", dic);
       
NSLog(@"%@, %@", [dic objectForKey:@"NSFileOwnerAccountName"], dic[@"NSFileOwnerAccountName"]);//字典通过key获取值,两种方式
       
//2)获取指定目录下文件及子目录
       
//使用递归的方式  获取当前目录及子目录下的所有文件及文件夹
       
NSArray *arr = [fm subpathsAtPath:dirPath];
       
//这种方法不是使用递归的方式实现
        arr = [fm
subpathsOfDirectoryAtPath:dirPath error:nil];
       
NSLog(@"%@", arr);
       
//3)获取指定目录下的子目录(不在获取后代路径,即不在获取子目录下的信息)
        arr = [fm
contentsOfDirectoryAtPath:dirPath error:nil];
        NSLog(@"%@", arr);


4、NSFileManager用法深入2
       //第一步,必须有文件管理对象
       
NSFileManager *fm = [NSFileManager defaultManager];
      
//如何创建目录(路径:/Users/ZacharyUE/Desktop/dir)
        NSString *createDirPath = @"/Users/ZacharyUE/Desktop/dir";
       
/*
         createDirectoryAtPath:@"
路径" withIntermediateDirectories:YES/NO
         YES/NO:
会把缺失文件夹补上来,后者如果上级文件夹确实,会报错
         attributes:
属性的字典 error:错误对象
        */

       
BOOL isYES = [fm createDirectoryAtPath:createDirPath withIntermediateDirectories:NO attributes:nil error:nil];
       
if (isYES) {
           
NSLog(@"%d", isYES);
        }

//如何创建文件
        NSString *str = @"shi最棒的!";//写入到@"/Users/ZacharyUE/Desktop/dir/me.txt";
        //以下的createDirPath = @"/Users/ZacharyUE/Desktop/dir/me.txt";
        //1writeToFile
       
//2createFileAtPath
       
/*
            createFileAtPath:@"
路径" contents:NSData类型的数据 attributes:文件的属性的字典
        
创建NSData:是一个处理二进制数据的类
        
NSString--------NSData
         */

       
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
       
BOOL isYES = [fm createFileAtPath:createDirPath contents:data attributes:nil];
        NSLog(@"%d", isYES);

//如何copy文件
       
NSString *copyPath = @"/Users/ZacharyUE/Desktop/dir/xxx/me.txt";
       
BOOL isYES = [fm copyItemAtPath:createDirPath toPath:copyPath error:nil];
        NSLog(@"%d", isYES);

//如何移动文件
       
NSString *movePath = @"/Users/ZacharyUE/Desktop/dir/aaa/me.txt";
        [fm moveItemAtPath:createDirPath toPath:movePath error:nil];

//如何删除文件,@"/Users/ZacharyUE/Desktop/dir/me.txt"
        [fm removeItemAtPath:createDirPath error:nil];

5、NSFileManager文件下载的思路
     1)发送请求给服务器,要求下载某个文件
     2)服务器发出响应,返回文件数据
     3)手机客户端利用NSData来存放服务器返回的文件数据
     4)利用NSFileManager将NSData里面的文件数据写到新的文件中

6、iOS沙盒(sandbox)机制
   每个iOS应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用的文件系统隔离,iOS系统不允许访问其他应用的应用沙盒。
   在iOS8中已经开放访问(extension),对几个固定系统区域的扩展机制。
   应用沙盒一般包含几个文件目录:应用程序包、Documents、Libaray(子目录Caches和Preferences)、tmp
   应用程序包:包含所有的资源文件和可执行文件。
   Documents:保存应用运行时生成的需要持久化的数据,iTunes会自动备份该目录。
   tmp:保存应用运行时所需的零时数据,使用完后相应地文件从该目录删除。未运行时,系统也可能清除该目录的文件,iTunes不会同步该目录。iPhone重启时,该目录下的文件会丢失。
   Libaray:存储程序的默认设置和其它状态信息,iTunes会自动备份该目录。
   Libaray/Caches:存储缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出时删除。
   Libaray/Preference:保存应用的所有偏好设置(配置信息\SQLite),iOS的Settings(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。

//沙盒路径获取方法:
       
//1)沙盒的路径
       
NSString *sandBoxPath = NSHomeDirectory();
       
NSLog(@"sandBoxPath = %@", sandBoxPath);//Mac下,用户根目录
       
//2tmp路径
       
NSString *tmpPath = NSTemporaryDirectory();
       
NSLog(@"tmpPath = %@", tmpPath);
       
//2Documents路径
      
// NSSearchPathForDirectoriesInDomains(要查找的目录, 是否使用主目录, YES/NO是否获取全路径)
       
NSArray *arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
       
NSLog(@"%@", arr);
       
//4Librarycaches同理
        arr =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
       
NSLog(@"%@", arr);
       
//5preferences路径,在Libaray的基础上,拼接/Preferences
        NSString *filePath = [arr lastObject];
        //stringByAppendingPathComponent用于拼接,也可以创建文件:@“Preferences/a.txt"
        NSString *str = [filePath stringByAppendingPathComponent:@"Preferences"];
        NSLog(@"%@", str);


7、常见的结构体
1)NSPoint和CGPoint的使用()
     /* Points. */
     //二维平面的一个点
struct CGPoint {
    CGFloat x;
    CGFloat y;
};
typedef struct CGPoint CGPoint;//NSPoint是CGPoint的别名,没区别

CGPoint c1;//c1CGPoint结构体类型的变量
        c1.
x = 10;
        c1.
y = 10;
       
CGPoint c2 = {10, 10};
       
//OC特有的赋值
       
CGPoint c3 = CGPointMake(10, 10);
        NSPoint c4 = NSMakePoint(5, 5);


2)NSSize和CGSize的使用(大小)
      /* Sizes. */
     //表示平面的面积
struct CGSize {
    CGFloat width;//宽
    CGFloat height;//高
};
typedef struct CGSize CGSize;

//同理,也有特有的赋值方式,形式与上面类似CGSizeMake和NSMakeSize
3)NSRect和CGRect的使用(矩形)
/* Rectangles. */
//表示从左上角某个点开始的矩形区域
struct CGRect {
    CGPoint origin;//开始点
    CGSize size;//大小
};
typedef struct CGRect CGRect;

CGRect r1;
        r1.origin.x = 0;
        r1.origin.y = 0;
        r1.size.width = 200;
        r1.size.height = 80;
       
        CGRect r2 = {{0, 0}, {10, 20}};
        //OC特有赋值方式
        CGRect r3 = CGRectMake(0, 0, 30, 80);
        NSRect r4 = NSMakeRect(0, 0, 89, 90);
      //快捷查看值的方法,转换为字符串
        NSLog(@"r4 = %@", NSStringFromRect(r4));
     //同理,上面的Size和Point都可以
4)常见结构体的使用注意
  苹果官方推荐使用CG开头



8、NSNumber的使用
   1)NSNumber的介绍和使用
     OC中处理数字的一个类
     NSArray和NSDictionary中只能存放OC对象,需要先将基本类型包装成对象,这样就可以存放到数组或字典
   2)NSNumber的创建
            int a = 10;
       
        NSNumber *intObj = [NSNumber numberWithInt:a];//其他类型同理
        NSArray *array = [NSArray arrayWithObjects:intObj, nil];
        NSLog(@"%@", array);
   3)从NSNumber对象中获取到基本数据类型
         float b =2.3f;
       
NSNumber *floatObj = [NSNumber numberWithFloat:b];
        [array
addObject:floatObj];
       
NSLog(@"%@", array);
       
       
//数组的第一个元素和第二个元素相加
       
//1)取出数组的元素
       
//2)把数组元素转换为基本数据类型
       
NSNumber *n1 = array[0];
       
int a1 = [n1 intValue];//获取对象的整形值
       
       
NSNumber *n2 = array[1];
       
float b1 = [n2 floatValue];
        a1 = a1 + b1;
        NSLog(@"%d", a1);

 简写形式@(变量名)@数值@YES,都是把变量、数值或YES包装成对象

9、NSValue的介绍和使用
     NSNumber是NSValue的子类,NSValue主要是把指针,CGRect结构体等包装成OC对象,以便存储。
     (int/float/char/pointers/structures/object ids)
     NSValue类的目标:允许以上数据类型的数据结构能够被添加到集合里,如NSArray和NSDictionary
     为了方便结构体和NSValue的转换,Foundation提供了一下方法:
     1)存储结构体到集合
      + (NSValue *)valueWithPoint:(NSPoint)point;
     + (NSValue *)valueWithSize:(NSSize)size;
     + (NSValue *)valueWithRect:(NSRect)rect;

      //创建一个结构体变量,保存一个点
       
CGPoint p1 = CGPointMake(10, 10);
       
//将结构体包装为NSValue对象
       
NSValue *pointObj = [NSValue valueWithPoint:p1];
       
NSMutableArray *array = [NSMutableArray arrayWithObjects:pointObj, nil];
       
NSLog(@"%@", array);
       
       
//创建一个结构体,保存Size
       
CGSize s1 = CGSizeMake(20, 20);
       
NSValue *sizeObj = [NSValue valueWithSize:s1];
        [array
addObject:sizeObj];
       
NSLog(@"%@", array);
       
//创建一个结构体,保存Rect
       
CGRect r1 = CGRectMake(1, 1, 22, 33);
        [array
addObject:[NSValue valueWithRect:r1]];
        NSLog(@"%@", array);
     2)从NSValue对象取出之前包装的结构体
     - (NSPoint)pointValue;
     - (NSSize)sizeValue;
     - (NSRect)rectValue;
     
      //取最后的值
       
NSValue *lastValue = [array lastObject];
       
NSRect r2 = [lastValue rectValue];
        NSLog(@"%@", NSStringFromRect(r2)); //转换为字符串

//自定义结构体
typedef struct data {
   
int year;
   
int month;
   
int day;
} MYData;

//定义结构体变量
       
MYData md = {2015, 9, 3};
       
//将自定义结构体包装成NSValue对象
       
//@encode(MYData) 作用,把MYData类型生成一个常量字符串描述
       
NSValue *mdObj = [NSValue valueWithBytes:&md objCType:@encode(MYData)];
       
//保存自定义结构体,到数组
       
NSMutableArray *arr = [NSMutableArray arrayWithObjects:mdObj, nil];
       
//从数组取出NSValue对象
       
MYData md1;
       [[arr objectAtIndex:0] getValue:&md1];//getValue获取的值,保存到md1
        //从对象中,取出结构体变量的值
        NSLog(@"%d-%d-%d", md1.year, md1.month, md1.day);



10、NSDate的介绍和使用
1)NSDate的介绍和使用
NSDate可以表示时间,可以进行一些常见的日期、时间处理。一个NSDate对象就代表一个时间,[NSDate date]返回的就是当前时间。
//NSDate OC中提供日期时间处理的一个类
       
//1)获取当前时间
       
NSDate *d1 = [NSDate date];//创建一个日期时间对象对象
       
//北京东八区,打印的时间(格林威治时间)+8 = 现在时间
        NSLog(@"%@", d1);

        //2)格式化显示时间
       
NSDateFormatter *formatter = [NSDateFormatter new];
       
//设置日期的显示格式
       
//yyyy:年份  MM:月份    dd:天数
       
//HH:24小时制  hh:12小时制
       
//mm:分钟数    ss:秒数
        formatter.
dateFormat = @"yyyyMMdd HH:mm:ss";
       
NSString *dateStr = [formatter stringFromDate:d1];
        NSLog(@"%@", dateStr);

         //3)计算时间
           
//1、计算明天的此刻时间(24小时之后的时间)
       
NSTimeInterval t = 60 * 60 * 24;
       
NSDate *tom = [NSDate dateWithTimeIntervalSinceNow:t];
       
       
NSDateFormatter *formatter = [NSDateFormatter new];//格式化显示
        formatter.
dateFormat = @"yyyy-MM-dd hh:mm:ss";
       
NSString *str = [formatter stringFromDate:tom];
       
NSLog(@"%@", str);
           
//2、计算昨天的此刻时间(-t24小时之前的时间)
       
NSDate *yest = [NSDate dateWithTimeIntervalSinceNow:-t];
        str = [formatter
stringFromDate:yest];
       
NSLog(@"%@", str);
           
//也可以用当前时间,进行加减时间
       
NSDate *now = [NSDate date];
       
NSDate *yest2 = [now addTimeInterval:-t];//该方法已经被放逐了
        str = [formatter
stringFromDate:yest2];
        NSLog(@"%@", str);

         //4)日期时间对象的使用
           
//1NSCalendar 日期类,可以帮助快速获取年月日 时分秒的信息
       
NSDate *d = [NSDate date];
       
//创建日期对象
       
NSCalendar *cal = [NSCalendar currentCalendar];
       
//参数:获取日期的哪个单元(可以多个单元,|)         当前日期对象
       
NSDateComponents *com = [cal components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:d];
       
NSLog(@"%ld-%ld-%ld", com.year, com.month, com.day);
            //2、时间差方法:components:<#(NSCalendarUnit)#> fromDate:<#(nonnull NSDate *)#> toDate:<#(nonnull NSDate *)#> options:<#(NSCalendarOptions)#>



11、集合对象的内存管理
1)集合内存管理
                   //创建对象
       
Person *p = [Person new]; //1
       
//定义数组,并且把P放到数组中
       
//规律:只要把对象放入数组,retainCount+1
        //NSArray *arr = [NSArray arrayWithObject:p];//2
        NSMutableArray *arr = [NSMutableArray array];
        [arr addObject:p];//2
//上面都是快速创建对象,会被加入自动释放池。如果是[[NSArray alloc] init]、copy或new,则不会加入自动释放池,则该对象不会被释放,不会调用dealloc
        NSLog(@"p.retainCount = %lu", p.retainCount);
        [p
release];
       
//规律2:数组被销毁时,对对象发送了一次release消息
       
//销毁顺序:数组先挂-----》数组向其中的对象也发送release
       
NSLog(@"p.retainCount = %lu", p.retainCount);
       
//结论:
       
//1)当对象被添加到数组中,对象的引用计数+1
       
//2)数组被销毁时,对对象发送了一次release消息
        //3)数组被销毁了,其中的对象不一定被销毁    
2)集合内存管理总结
1、当调用alloc、new、copy(mutablecopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease。因为不会加入自动释放池。
2、retain和release必须成对出现
3、当一个对象添加集合,retain+1,retainCount+1
   当一个集合(快速创建)被销毁,集合所有对象均被release一次,retainCount-1
   当一个对象从集合中移除,这个对象会被release一次,retainCount-1
4、普遍规律:当方法名是add\insert开头   计数器+1
           当方法名是remove\delete开头,计数器-1



12、copy概念及入门
1、copy概念
copy:复制,拷贝,是产生一个副本的过程。
对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容。源文件和副本文件,互不影响。
copy功能:一个对象可以调用copy或mutableCopy方法创建一个副本对象
        copy:创建不可变副本(如NSString)
        mutableCopy:创建可变副本(如NSMutableString)
copy功能的前提:1)浅拷贝copy:需要遵守NSCopy协议,实现copyWithZone:方法
                  @protocol NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
   @end   
              2)深拷贝mutableCopy:需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
                                                 @protocol NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
   @end
2、copy快速入门
不可变对象,copy      产生不可变对象
不可变对象,mutableCopy   产生可变对象
可变对象,copy         产生不可变对象
可变对象,mutableCopy   产生可变对象


13、copy与内存管理
浅拷贝:只是拷贝了地址,并没有真正的分配新的内存空间(源对象引用计数+1,副本对象指向源对象,两者一样)
深拷贝:分配了新的内存空间(源对象引用计数不变,副本对象为1)

14、@property中的copy关键字
1)MRC
     1、copy:只用于NSString和block
     2、retain:除NSString和block以外的对象
     3、assign:基本数据类型、枚举、结构体(非OC对象)。当两个对象互相引用时,一段assign,一段retain
2)ARC
     1、copy:只用于NSString和block
     2、strong:除NSString和block以外的对象
     3、weak:当两个对象互相引用时,一段weak,一段strong
     4、assign:基本数据类型、枚举、结构体(非OC对象)

@property (nonatomic, copy) NSString *name;
#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
   
@autoreleasepool {
   
       
Person *p = [[Person alloc] init];

       
NSMutableString *str = [NSMutableString string];
        [str
appendString:@"xxx"];
        p.
name = str;
       
NSLog(@"%@", p.name);
       
//使用copy时,防止这种无理的赋值。name得到的只是str的副本,再改变str不会影响name
        [str
appendString:@"ooo"];
       
NSLog(@"%@", p.name);
       
       
       
       
       
        [p
release];
    }
   
return 0;
}


15、为自定义的类实现copy操作
步骤:1、新建Person类
     2、为Person类实现copy操作
          1)让Person类遵守NSCopying协议
          2)实现copyWithZone方法,该方法返回一个对象的副本
          3)在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致,且返回该对象
     3、创建Person对象,调用copy方法,查看地址
参数zone:表示空间,指定了zone,就可以指定新建对象对应的内存空间。如今开发中,zone几乎可以忽略

例子:1、 @interface Dog : NSObject<NSCopying>
@property (nonatomic, assign) int tuiNum;
@property (nonatomic,assign) int speed;
@end

     2、 @implementation Dog
- (id)copyWithZone:(nullable NSZone *)zone {
   
   
    NSLog(@"copy完毕");
    //互不影响,需申请新空间
    Dog *d = [[Dog alloc] init];
    d.speed = self.speed;
    d.tuiNum = self.tuiNum;
    //返回新空间的地址
    return d;
}
@end

3、  
       
Dog *dog = [Dog new];
        dog.
speed = 230;
        dog.
tuiNum = 8;
       
//虽然重写copyWithZone方法,依然调用copy。历史原因
       
Dog *yellowDog = [dog copy];
        NSLog(@"%d,%d", yellowDog.speed, yellowDog.tuiNum);



16、简单的单例模式实现
1)理解单例模式概念
单例模式(singleton):类的对象成为系统中唯一的实例,提供一个访问点,供客户类共享资源
单例使用场景:1、类只能够有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法
            2、这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码
2)单例模式的实现
1、SingletonTools单例工具类
#import <Foundation/Foundation.h>

@interface SingletonTools : NSObject<NSCopying>
@property (nonatomic, assign) int num;
@property (nonatomic, copy) NSString *text;
//单例的类,提供一个接入点
+(
instancetype)shareInstances;
//防止创建新的对象或者破坏该单例对象,需重写以下方法
-(id)copyWithZone:(NSZone *)zone;
+(
id)allocWithZone:(NSZone *)zone;
-(
id)retain;
-(
NSUInteger)retainCount;
-(
oneway void)release;
-(
id)autorelease;
@end
-------------------------------------------------------------------------------
#import "SingletonTools.h"
//定义一个全局变量
static SingletonTools *instances = nil;//static增长使用周期,下次使用还有值
@implementation SingletonTools
//单例接入点方法
+(
instancetype)shareInstances {
   
//目的:保证对象必须唯一
   
if (instances == nil) {
       
//创建一个对象
       
instances = [[SingletonTools alloc] init];
       
return instances;
    }
   
return instances;
}

//防止创建新的对象或者破坏该单例对象,需重写以下方法
-(
id)copyWithZone:(NSZone *)zone {
   
return self;
}
+(
id)allocWithZone:(NSZone *)zone {
   
//线程保护
   
@synchronized(self) {
       
if (instances == nil) {
           
//调用父类alloc
           
instances = [super allocWithZone:zone];
           
return instances;//此处有待考究,没有关锁,就退出了
        }
       
return instances;
    }
}
-(
id)retain {
   
return self;
}
-(
NSUInteger)retainCount {
    return  1;
}
-(
oneway void)release {
   
}
-(
id)autorelease {
   
return self;
}
@end



2、Person类
#import <Foundation/Foundation.h>

@interface Person : NSObject
-(
void) run;
@end
----------------------------------------------------------------------------------------
#import "Person.h"
#import
"SingletonTools.h"
@implementation Person
-(
void) run {
   
//创建单例对象
   
SingletonTools *st = [SingletonTools shareInstances];
    st.
num = 500;
    st.
text = @"xxxxx";
}
@end



3、Dog类
#import <Foundation/Foundation.h>

@interface Dog : NSObject
-(
void)run;
@end
--------------------------------------------------------------------------------------
#import "Dog.h"
#import
"SingletonTools.h"
@implementation Dog
-(
void)run {
   
SingletonTools *st = [SingletonTools shareInstances];
   
NSLog(@"%d,%@", st.num, st.text);
}

@end



4、main
#import <Foundation/Foundation.h>
#import
"Person.h"
#import
"Dog.h"

int main(int argc, const char * argv[]) {
   
@autoreleasepool {
       
Person *p = [Person new];
        [p
run];
       
       
Dog *d = [Dog new];
        [d
run];//通过单例,d也可以访问p的数据
       
//而且在重写方法后,并不需要在意在Dog类的run中是如何创建单例对象(快速或者alloc
       
//单例实现了两个不相干的类的数据传输
    }
   
return 0;
}
Console:500,xxxxx
发布了43 篇原创文章 · 获赞 1 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章