IOS 基础知识-Foundation框架2

IOS 基础知识-Foundation框架2

常见的结构体

本小节知识点:

  1. 【理解】NSPoint和CGPoint
  2. 【理解】NSSize和CGSize
  3. 【理解】NSRect和CGRect
  4. 【理解】常见的结构体使用注意

1.NSPoint和CGPoint

  • CGPoint和NSPoint是同义的
typedef CGPoint NSPoint;

CGPoint的定义
struct CGPoint {
  CGFloat x;
  CGFloat y;
};
typedef struct CGPoint CGPoint;
typedef double CGFloat;
  • 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.NSRect和CGRect

  • CGRect和NSRect是同义的
typedef CGRect NSRect;

CGRect的定义
struct CGRect {
  CGPoint origin;
  CGSize size;
};
typedef struct CGRect CGRect;
  • CGRect代表的是二维平面中的某个物体的位置和尺寸
    • 可以使用CGRectMake和NSMakeRect函数创建CGRect

4.常见的结构体使用注意

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

集合对象的内存管理

本小节知识点:

  1. 【掌握】集合对象的内存管理
  2. 【理解】集合对象内存管理总结

1.集合对象的内存管理

  • 当一个对象加入到集合中,那么该对象的引用计数会+1
  • 当集合被销毁的时候,集合会向集合中的元素发送release消息
    NSMutableArray *arr = [[NSMutableArray alloc] init];

    Person *p = [[Person alloc] init];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [arr addObject:p];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [p release];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [arr release];
  • 当一个对象加入到集合中,那么该对象的引用计数会+1
  • 当把一个对象从集合中移除时,会向移除的元素发送release消息
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    Person *p = [[Person alloc] init];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [arr addObject:p];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [arr removeObject:p];
    NSLog(@"retainCount = %lu", [p retainCount]);
    [p release];
    [arr release];

2.集合对象内存管理总结

  • 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

NSArray基本概念

本小节知识点:

  1. 【理解】NSArray基本概念
  2. 【理解】NSArray创建方式
  3. 【理解】NSArray注意事项
  4. 【理解】NSArray常用方法
  5. 【理解】NSArray简写形式

1.NSArray的基本概念

  • 什么是NSArray?

    • NSArray是OC中的数组类,开发中建议尽量使用NSArray替代C语言中的数组
    • C语言中数组的弊端
      • int array[4] = {10, 89, 27, 76};
      • 只能存放一种类型的数据.(类型必须一致)
      • 不能很方便地动态添加数组元素、不能很方便地动态删除数组元素(长度固定)
  • NSArray的使用注意

    • 只能存放任意OC对象, 并且是有顺序的
    • 不能存储非OC对象, 比如int\float\double\char\enum\struct等
    • 它是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的, 不能删除里面的元素, 也不能再往里面添加元素

2.NSArray的创建方式

  • + (instancetype)array;

  • + (instancetype)arrayWithObject:(id)anObject;

  • + (instancetype)arrayWithObjects:(id)firstObj, …;

  • + (instancetype)arrayWithArray:(NSArray *)array;

  • + (id)arrayWithContentsOfFile:(NSString *)path;

  • + (id)arrayWithContentsOfURL:(NSURL *)url;


3.NSArray 的使用注意事项

  • NSArray使用NSLog()输出内容,内容是小括号的格式。

  • NSArray中不能存储nil,因为NSArray认为nil是数组的结束(nil是数组元素结束的标记)。nil就是0。0也是基本数据类型,不能存放到NSArray中。

    NSArray *arr = [NSArray arrayWithObjects:@"lnj", nil ,@"lmj",@"jjj", nil];
    NSLog(@"%@", arr);
输出结果:
(
    lnj
)

4.NSArray的常用方法

  • - (NSUInteger)count;

    • 获取集合元素个数
  • - (id)objectAtIndex:(NSUInteger)index;

    • 获得index位置的元素
  • - (BOOL)containsObject:(id)anObject;

    • 是否包含某一个元素
  • - (id)lastObject;

    • 返回最后一个元素
  • - (id)firstObject;

    • 返回最后一个元素
  • - (NSUInteger)indexOfObject:(id)anObject;

    • 查找anObject元素在数组中的位置(如果找不到,返回-1)
  • - (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range;

    • 在range范围内查找anObject元素在数组中的位置

5.NSArray的简写形式

  • 自从2012年开始, Xcode的编译器多了很多自动生成代码的功能, 使得OC代码更加精简

  • 数组的创建

    • 之前
[NSArray arrayWithObjects:@"Jack", @"Rose", @"Jim", nil];
+ 现在
@[@"Jack", @"Rose", @"Jim"];
  • 数组元素的访问
    • 之前
[array objectAtIndex:0];
+ 现在
array[0];

NSArray 遍历

本小节知识点:

  1. 【理解】NSArray的下标遍历
  2. 【理解】NSArray的快速遍历
  3. 【理解】NSArray 使用block进行遍历
  4. 【理解】NSArray给所有元素发消息

1.NSArray的下标遍历

    NSArray *arr = @[p1, p2, p3, p4, p5];
    for (int i = 0; i < arr.count; ++i) {
        Person *p = arr[i];
        [p say];
    }

2.NSArray的快速遍历

    NSArray *arr = @[p1, p2, p3, p4, p5];
   for (Person *p in arr) {
        [p say];
    }

3.NSArray 使用block进行遍历

    [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"obj = %@, idx = %lu", obj, idx);
        Person *p = obj;
        [p say];
    }];

4.NSArray给所有元素发消息

  • 让集合里面的所有元素都执行aSelector这个方法
    • - (void)makeObjectsPerformSelector:(SEL)aSelector;
    • - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)argument;
    // 让数组中所有对象执行这个方法
    // 注意: 如果数组中的对象没有这个方法会报错
//    [arr makeObjectsPerformSelector:@selector(say)];
    [arr makeObjectsPerformSelector:@selector(eat:) withObject:@"bread"];

NSArray排序

本小节知识点:

  1. 【理解】NSArray排序

1.NSArray排序

  • Foundation自带类排序
NSArray *arr = @[@(1), @(9), @(5), @(2)];
NSArray *newArr = [arr sortedArrayUsingSelector:@selector(compare:)];
  • 自定义类排序
    NSArray *arr = @[p1, p2, p3, p4, p5];
    //    默认按照升序排序
    NSArray *newArr = [arr sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
        return obj1.age > obj2.age;
    }];
    NSLog(@"%@", newArr);

NSArray 与字符串

本小节知识点:

  1. 【理解】把数组元素链接成字符串
  2. 【理解】字符串分割方法

1.把数组元素链接成字符串

  • - (NSString *)componentsJoinedByString:(NSString *)separator;
    • 这是NSArray的方法, 用separator作拼接符将数组元素拼接成一个字符串
    NSArray *arr = @[@"lnj", @"lmj", @"jjj", @"xcq"];
    NSString *res = [arr componentsJoinedByString:@"*"];
    NSLog(@"res = %@", res);
输出结果:
lnj*lmj*jjj*xcq

2.字符串分割方法

  • - (NSArray *)componentsSeparatedByString:(NSString *)separator;
    • 这是NSString的方法,将字符串用separator作为分隔符切割成数组元素
    NSString *str = @"lnj-lmj-jjj-xcq";
    NSArray *arr = [str componentsSeparatedByString:@"-"];
    NSLog(@"%@", arr);

输出结果:
(
    lnj,
    lmj,
    jjj,
    xcq
)


NSArray文件读写

本小节知识点:

  1. 【理解】NSArray数据写入到文件中
  2. 【理解】从文件中读取数据到NSArray中

1.NSArray数据写入到文件中

    NSArray *arr = @[@"lnj", @"lmj", @"jjj", @"xcq"];
    BOOL flag = [arr writeToFile:@"/Users/LNJ/Desktop/persons.plist" atomically:YES];
    NSLog(@"%i", flag);

2.从文件中读取数据到NSArray中

    NSArray *newArr = [NSArray arrayWithContentsOfFile:@"/Users/LNJ/Desktop/persons.xml"];
    NSLog(@"%@", newArr);

自定义的类实现copy操作

本小节知识点:

  1. 【理解】自定义类实现copy操作

1.自定义类实现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;
}

NSDate

本小节知识点:

  1. 【理解】NSDate基本概念
  2. 【理解】格式化日期
  3. 【理解】日期时间对象

1.NSDate基本概念

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

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

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

    NSDate *now = [NSDate date];
    NSLog(@"now = %@", now);
     // 设置转换后的目标日期时区
     NSTimeZone *zone = [NSTimeZone systemTimeZone];
     // 得到源日期与世界标准时间的偏移量
     NSInteger interval = [zone secondsFromGMTForDate: date];
     NSLog(@"interval = %lu", interval);
     // 在当前时间基础上追加时区差值
     now = [now dateByAddingTimeInterval:interval];
     NSLog(@"%@", date);

2.格式化日期

  • NSDate -> NSString
    // 1.创建时间
    NSDate *now = [NSDate date];
    // 2.创建时间格式化
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    // 3.指定格式
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // 4.格式化时间
    NSString *str = [formatter stringFromDate:now];
    NSLog(@"%@", str);
  • NSString -> NSDate
    NSString *str = @"2015-06-28 19:53:24";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *date = [formatter dateFromString:str];
    NSLog(@"%@", date);

3.日期时间对象

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

  • 获得NSCalendar对象

NSCalendar *calendar = [NSCalendar currentCalendar];
  • 获得年月日
- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)date;
    NSDate *date = [NSDate date];
    // 1.创建日历对象
    NSCalendar *calendar = [NSCalendar currentCalendar];
    // 2.利用日历对象获取年月日时分秒
    NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *cmps =[calendar components:type fromDate:date];
    NSLog(@"year = %lu", cmps.year);
    NSLog(@"month = %lu", cmps.month);
    NSLog(@"day = %lu", cmps.day);
    NSLog(@"hour = %lu", cmps.hour);
    NSLog(@"minute = %lu", cmps.minute);
    NSLog(@"second = %lu", cmps.second);
    NSLog(@"date = %@", date);
  • 比较两个日期的差距
- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSCalendarOptions)opts;

    // 1.确定时间
    NSString *time1 = @"2015-06-23 12:18:15";
    NSString *time2 = @"2015-06-28 10:10:10";
    // 2.将时间转换为date
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *date1 = [formatter dateFromString:time1];
    NSDate *date2 = [formatter dateFromString:time2];
    // 3.创建日历
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    // 4.利用日历对象比较两个时间的差值
    NSDateComponents *cmps = [calendar components:type fromDate:date1 toDate:date2 options:0];
    // 5.输出结果
    NSLog(@"两个时间相差%ld年%ld月%ld日%ld小时%ld分钟%ld秒", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second);

NSDictionary基本概念

本小节知识点:

  1. 【理解】NSDictionar基本概念
  2. 【理解】NSDictionary的创建
  3. 【理解】NSDictionary的遍历
  4. 【理解】NSDictionary文件操作

1.NSDictionar基本概念

  • 什么是NSDictionary
    • NSDictionary翻译过来叫做”字典”
    • 日常生活中,“字典”的作用:通过一个拼音或者汉字,就能找到对应的详细解释
    • NSDictionary的作用类似:通过一个key,就能找到对应的value
    • NSDictionary是不可变的, 一旦初始化完毕, 里面的内容就无法修改

2.NSDictionary的创建

+ (instancetype)dictionary;
+ (instancetype)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
+ (instancetype)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
+ (id)dictionaryWithContentsOfFile:(NSString *)path;
+ (id)dictionaryWithContentsOfURL:(NSURL *)url;
  • NSDictionary创建简写
    • 以前
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"lnj", @"name", @"12345678", @"phone", @"天朝", @"address", nil];
+ 现在
NSDictionary *dict = @{@"name":@"lnj", @"phone":@"12345678", @"address":@"天朝"};
  • NSDictionary获取元素简写
    • 以前
[dict objectForKey:@"name”];
+ 现在
dict[@"name”];
  • 键值对集合的特点
    • 字典存储的时候,必须是"键值对"的方式来存储(同时键不要重复)
    • 键值对中存储的数据是"无序的".
    • 键值对集合可以根据键, 快速获取数据.

3.NSDictionary的遍历

  • - (NSUInteger)count;

    • 返回字典的键值对数目
  • - (id)objectForKey:(id)aKey;

    • 根据key取出value
  • 快速遍历

    NSDictionary *dict = @{@"name":@"lnj", @"phone":@"12345678", @"address":@"天朝"};
    for (NSString *key in dict) {
        NSLog(@"key = %@, value = %@", key, dict[key]);
    }
  • Block遍历
    [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
        NSLog(@"key = %@, value = %@", key, obj);
    }];


4.NSDictionary文件操作

  • 将字典写入文件中

    • - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
    • - (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;
    • 存结果是xml文件格式,但苹果官方推荐为plist后缀。
  • 示例

    NSDictionary *dict = @{@"name":@"lnj", @"phone":@"12345678", @"address":@"天朝"};
    BOOL flag = [dict writeToFile:@"/Users/LNJ/Desktop/dict.plist" atomically:YES];
    NSLog(@"flag = %i", flag);
  • 从文件中读取字典
NSDictionary *newDict = [NSDictionary dictionaryWithContentsOfFile:@"/Users/LNJ/Desktop/dict.plist"];
    NSLog(@"newDict = %@", newDict);

NSFileManager

本小节知识点:

  1. 【理解】NSFileManager介绍
  2. 【理解】NSFileManager用法(常见的判断)
  3. 【理解】NSFileManager的文件访问
  4. 【理解】NSFileManager的文件操作

1.NSFileManager介绍

  • 什么是NSFileManager

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

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

2.NSFileManager用法

  • - (BOOL)fileExistsAtPath:(NSString *)path;
    • path这个文件\文件夹是否存在
    NSFileManager *manager = [NSFileManager defaultManager];
    // 可以判断文件
    BOOL flag = [manager fileExistsAtPath:@"/Users/LNJ/Desktop/lnj.txt"];
    NSLog(@"flag = %i", flag);
    // 可以判断文件夹
    flag = [manager fileExistsAtPath:@"/Users/LNJ/Desktop/未命名文件夹"];
    NSLog(@"flag = %i", flag);
  • - (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;
    • path这个文件\文件夹是否存在, isDirectory代表是否为文件夹
    NSFileManager *manager = [NSFileManager defaultManager];
    BOOL directory = NO;
    BOOL flag = [manager fileExistsAtPath:@"/Users/LNJ/Desktop/未命名文件夹" isDirectory:&directory];
    NSLog(@"flag = %i, directory = %i", flag, directory);
  • - (BOOL)isReadableFileAtPath:(NSString *)path;

    • path这个文件\文件夹是否可读
  • - (BOOL)isWritableFileAtPath:(NSString *)path;

    • path这个文件\文件夹是否可写
    • 系统目录不允许写入
  • - (BOOL)isDeletableFileAtPath:(NSString *)path;

    • path这个文件\文件夹是否可删除
    • 系统目录不允许删除

3.NSFileManager的文件访问

  • - (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error;
    • 获得path这个文件\文件夹的属性
    NSFileManager *manager = [NSFileManager defaultManager];
    NSDictionary *dict = [manager attributesOfItemAtPath:@"/Users/LNJ/Desktop/lnj.txt" error:nil];
    NSLog(@"dit = %@", dict);
  • - (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;

    • 获得path的当前子路径
  • - (NSData *)contentsAtPath:(NSString *)path;

    • 获得文件内容
    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *paths = [manager contentsOfDirectoryAtPath:@"/Users/LNJ/Desktop/" error:nil];
    NSLog(@"paths = %@", paths);
  • - (NSArray *)subpathsAtPath:(NSString *)path;
  • - (NSArray *)subpathsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;
    • 获得path的所有子路径
    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *paths = [manager subpathsAtPath:@"/Users/LNJ/Desktop/"];
    NSLog(@"paths = %@", paths);

4.NSFileManager的文件操作

  • - (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)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error;

    • 创建文件夹(createIntermediates为YES代表自动创建中间的文件夹)
    NSFileManager *manager = [NSFileManager defaultManager];
    BOOL flag = [manager createDirectoryAtPath:@"/Users/LNJ/Desktop/test" withIntermediateDirectories:YES attributes:nil error:nil];
    NSLog(@"flag = %i", flag);
  • - (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
    • 创建文件(NSData是用来存储二进制字节数据的)
    NSString *str = @"lnj";
    NSData  *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    NSFileManager *manager = [NSFileManager defaultManager];
    BOOL flag = [manager createFileAtPath:@"/Users/LNJ/Desktop/abc.txt" contents:data attributes:nil];
    NSLog(@"flag = %i", flag);

NSMutableArray基本概念

本小节知识点:

  1. 【理解】NSMutableArray介绍
  2. 【理解】NSMutableArray基本用法
  3. 【理解】NSMutableArray 错误用法

1.NSMutableArray介绍

  • 什么是NSMutableArray
    • NSMutableArray是NSArray的子类
    • NSArray是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的, 不能删除里面的元素, 也不能再往里面添加元素
    • NSMutableArray是可变的,随时可以往里面添加\更改\删除元素

2.NSMutableArray基本用法

  • 创建空数组
NSMutableArray *arr = [NSMutableArray array];
  • 创建数组,并且指定长度为5,此时也是空数组
NSMutableArray *arr2 = [[NSMutableArray alloc] initWithCapacity:5];
  • 创建一个数组,包含两个元素
NSMutableArray *arr3 = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
  • 调用对象方法创建数组
NSMutableArray *arr4 = [[NSMutableArray alloc] initWithObjects:@"1",@"2", nil];
  • - (void)addObject:(id)object;

    • 添加一个元素
  • - (void)addObjectsFromArray:(NSArray *)array;

    • 添加otherArray的全部元素到当前数组中
  • - (void)insertObject:(id)anObject atIndex:(NSUInteger)index;

    • 在index位置插入一个元素
  • - (void)removeLastObject;

    • 删除最后一个元素
  • - (void)removeAllObjects;

    • 删除所有的元素
  • - (void)removeObjectAtIndex:(NSUInteger)index;

    • 删除index位置的元素
  • - (void)removeObject:(id)object;

    • 删除特定的元素
  • - (void)removeObjectsInRange:(NSRange)range;

    • 删除range范围内的所有元素
  • - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;

    • 用anObject替换index位置对应的元素
  • - (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2;

    • 交换idx1和idx2位置的元素

3.NSMutableArray 错误用法

  • 不可以使用@[]创建可变数组
NSMutableArray *array = @[@"lnj", @"lmj", @"jjj"];
// 报错, 本质还是不可变数组
[array addObject:@“Peter”];

NSMutableDictionary基本概念

本小节知识点:

  1. 【理解】NSMutableDictionary 基本概念
  2. 【理解】NSMutableDictionary 常用方法
  3. 【理解】NSMutableDictionary 简写
  4. 【理解】NSDictionary和NSArray对比

1.NSMutableDictionary 基本概念

  • 什么是NSMutableDictionary
    • NSMutableDictionary是NSDictionary的子类
    • NSDictionary是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的,不能删除里面的元素, 也不能再往里面添加元素
    • NSMutableDictionary是可变的,随时可以往里面添加\更改\删除元素

2.NSMutableDictionary的常见操作

  • - (void)setObject:(id)anObject forKey:(id )aKey;

    • 添加一个键值对(会把aKey之前对应的值给替换掉)
  • - (void)removeObjectForKey:(id)aKey;

    • 通过aKey删除对应的value
  • - (void)removeAllObjects;

    • 删除所有的键值对

3.NSMutableDictionary的简写

  • 设置键值对
    • 以前
[dict setObject:@"Jack" forKey:@"name”];
+ 现在
dict[@"name"] = @"Jack";

4.NSDictionary和NSArray对比

  • NSArray和NSDictionary的区别

    • NSArray是有序的,NSDictionary是无序的
    • NSArray是通过下标访问元素,NSDictionary是通过key访问元素
  • NSArray的用法

    • 创建
@[@"Jack", @"Rose"] (返回是不可变数组)
+ 访问
id d = array[1];
+ 赋值
array[1] = @"jack";
  • NSDictionary的用法
    +创建
@{ @"name" : @"Jack", @"phone" : @"10086" } (返回是不可变字典)
+ 访问
id d = dict[@"name"];
+ 赋值
dict[@"name"] = @"jack";

NSNumber

本小节知识点:

  1. 【理解】NSNumber基本概念
  2. 【理解】NSNumber的创建
  3. 【理解】从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

本小节知识点:

  1. 【理解】NSValue基本概念
  2. 【理解】常见结构体的包装
  3. 【理解】任意数据的包装

1.NSValue基本概念

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

  • NSValue可以包装任意值

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

2. 常见结构体的包装

  • 为了方便 结构体 和NSValue的转换,Foundation提供了以下方法
  • 将结构体包装成NSValue对象
+ (NSValue *)valueWithPoint:(NSPoint)point;
+ (NSValue *)valueWithSize:(NSSize)size;
+ (NSValue *)valueWithRect:(NSRect)rect;
  • 从NSValue对象取出之前包装的结构体
- (NSPoint)pointValue;
- (NSSize)sizeValue;
- (NSRect)rectValue;

3.任意数据的包装

  • NSValue提供了下列方法来包装任意数据
+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;
+ value参数 : 所包装数据的地址
+ type参数 : 用来描述这个数据类型的字符串, 用@encode指令来生成

- 从NSValue中取出所包装的数据
- (void)getValue:(void *)value;

@property中的copy关键字

本小节知识点:

  1. 【理解】@property中的copy的作用
  2. 【理解】@property内存管理策略选择

1.@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];

2.@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对象)

单例设计模式

本小节知识点:

  1. 【理解】单例模式概念
  2. 【理解】简单的单例模式实现

1.单例模式概念

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

    • 单例模式的意图是是的类的对象成为系统中唯一的实例,?供一个访问点,供客户类 共享资源。
  • 什么情况下使用单例?

    • 1、类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方 法。
    • 2、这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
  • 单例设计模式的要点:

      1. 某个类只能有一个实例。
    • 2)他必须自行创建这个对象
    • 3)必须自行向整个系统?供这个实例;
    • 4)为了保证实例的唯一性,我们必须将
    • 5)这个方法必须是一个静态类

2.简单的单例模式实现

#define interfaceSingleton(name)  +(instancetype)share##name


#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name)  \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC

#define implementationSingleton(name)  \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return  MAXFLOAT; \
}
#endif



copy与内存管理

本小节知识点:

  1. 【理解】copy与内存管理

1.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

提示可以创建iOS项目演示


Copy

本小节知识点:

  1. 【理解】copy基本概念
  2. 【理解】Copy的使用
  3. 【理解】copy快速入门

1.copy基本概念

  • 什么是copy

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

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

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

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

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

##2.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

2.深复制和浅复制

  • 浅复制(浅拷贝,指针拷贝,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);
  • 只有源对象和副本对象都不可变时,才是浅复制,其它都是深复制

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值