一. 字符串 API

1. NSString 用法简介

(1) NSString API 介绍

NSString 功能​ : 

-- ​创建字符串​ : 使用 init 开头的实例方法, 也可以使用 String 开头的方法;

// init 开头方法创建字符串
unichar data[5] = {97, 98, 99, 100, 101};
NSString * str = [[NSString alloc] initWithCharacters : data length : 5];
// string 开头方法创建字符串
char * con_str = "Hello World";
NSString * str1 = [NSString stringWithUTF8String : con_str];

-- ​字符串获取​ : 读取文件 或 网络 URL 初始化字符串;

-- ​字符串写出​ : 字符串内容 写入 文件 或 URL;

-- ​长度获取​ : 获取字符串长度, 既可获取字符串内包含的字符个数, 又可获取字符串包含的字节个数;

// 字符串个数 字节数统计
NSLog(@"str char count is : %lu", [str length]);
NSLog(@"str utf8 byte count is : %lu", [str lengthOfBytesUsingEncoding : NSUTF8StringEncoding]);

--​ 获取子字符串​ : 既可以获取指定位置的字符, 又可以获取指定范围的字符串;

// 获取 前 5 个字符组成的字符串
NSString * str5 = [str3 substringToIndex : 5];
// 获取 从 第五个字符开始的字符串
NSString * str6 = [str3 substringFromIndex : 5];
// 获取 从 第五个 到 第九个 字符串
NSString * str7 = [str3 substringWithRange : NSMakeRange(5, 9)];

--​ 获取 C 字符串​ : 获取 NSString * 对应的 char * 字符串;

-- ​连接字符串​ : 将 2 个字符串连接;

//字符串拼接
NSString * str3 = [str2 stringByAppendingString : @", append this"];
NSString * str4 = [str2 stringByAppendingFormat : @", append %@", @"format"];

-- ​分隔字符串​ : 将 一个 字符串分成两个;

-- ​查找 字符 或 子字符串​ : 查找字符串内指定的字符 和 子字符串;

// 获取 "append" 出现的位置
NSRange pos = [str3 rangeOfString : @"append"];
NSLog(@"append position from %ld, length %ld", pos.location, pos.length);

-- ​替换字符串​ : 

-- ​比较字符串​ : 

-- ​字符串大小比较​ : 

-- ​对字符串中得字符进行大小写转换​ : 

// 大小写转换
NSString * str8 = [str2 uppercaseString];
NSLog(@"str8 : %@", str8);

(2) NSString 示例代码

示例代码​ : 

/*************************************************************************
> File Name: OCNSStringDemo.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 17:04:29 2015
************************************************************************/
#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
// init 开头方法创建字符串
unichar data[5] = {97, 98, 99, 100, 101};
NSString * str = [[NSString alloc] initWithCharacters : data length : 5];

// string 开头方法创建字符串
char * con_str = "Hello World";
NSString * str1 = [NSString stringWithUTF8String : con_str];

NSLog(@"str : %@, str1 : %@", str, str1);

// 将字符串写入文件
[str1 writeToFile : @"octopus.txt"
atomically : YES
encoding : NSUTF8StringEncoding
error : nil];

// 从文件读取字符串
NSString * str2 = [NSString stringWithContentsOfFile : @"octopus.txt"
encoding : NSUTF8StringEncoding
error : nil];

NSLog(@"str2 : %@", str2);

//字符串拼接
NSString * str3 = [str2 stringByAppendingString : @", append this"];
NSString * str4 = [str2 stringByAppendingFormat : @", append %@", @"format"];

NSLog(@"str3 : %@, str4 : %@", str3, str4);

// 字符串个数 字节数统计
NSLog(@"str char count is : %lu", [str length]);
NSLog(@"str utf8 byte count is : %lu", [str lengthOfBytesUsingEncoding : NSUTF8StringEncoding]);

// 获取 前 5 个字符组成的字符串
NSString * str5 = [str3 substringToIndex : 5];
// 获取 从 第五个字符开始的字符串
NSString * str6 = [str3 substringFromIndex : 5];
// 获取 从 第五个 到 第九个 字符串
NSString * str7 = [str3 substringWithRange : NSMakeRange(5, 9)];

NSLog(@"str5 : %@, str6 : %@, str7 : %@", str5, str6, str7);

// 获取 "append" 出现的位置
NSRange pos = [str3 rangeOfString : @"append"];
NSLog(@"append position from %ld, length %ld", pos.location, pos.length);

// 大小写转换
NSString * str8 = [str2 uppercaseString];
NSLog(@"str8 : %@", str8);


}
}

-- ​执行结果​ : 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCNSStringDemo.m 
bogon:6.6 octopus$ ./a.out
2015-10-06 17:52:40.007 a.out[1095:507] str : abcde, str1 : Hello World
2015-10-06 17:52:40.018 a.out[1095:507] str2 : Hello World
2015-10-06 17:52:40.018 a.out[1095:507] str3 : Hello World, append this, str4 : Hello World, append format
2015-10-06 17:52:40.019 a.out[1095:507] str char count is : 5
2015-10-06 17:52:40.020 a.out[1095:507] str utf8 byte count is : 5
2015-10-06 17:52:40.020 a.out[1095:507] str5 : Hello, str6 : World, append this, str7 : World, a
2015-10-06 17:52:40.021 a.out[1095:507] append position from 13, length 6
2015-10-06 17:52:40.021 a.out[1095:507] str8 : HELLO WORLD

2. NSMutableString 可变字符串

(1) NSMutableString 简介

NSString 与 NSMutableString 对比​ : 

-- ​NSString 缺陷​ : NSString 字符串一旦被创建, 字符串序列是不可改变的;

-- ​NSMutableString 优点​ : NSString 中所有的方法, NSMutableString 都可以调用, NSMutableString 对象可以当做 NSString 对象使用;

(2) NSMutableString 源码示例

源码示例​ : 

/*************************************************************************
> File Name: OCNSMutableStringTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 18:03:28 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
NSMutableString * str = [NSMutableString stringWithString : @"Hello World"];

NSLog(@"str : %@", str);

// 字符串追加
[str appendString : @" Octopus"];
NSLog(@"str : %@", str);

[str insertString : @"Insert " atIndex : 6];
NSLog(@"str : %@", str);

[str deleteCharactersInRange : NSMakeRange (6, 2)];
NSLog(@"str : %@", str);

[str replaceCharactersInRange : NSMakeRange(6, 9)
withString : @" Replace "];
NSLog(@"str : %@", str);
}
}

-- ​运行结果​ : 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCNSMutableStringTest.m 
bogon:6.6 octopus$ ./a.out
2015-10-06 18:44:04.498 a.out[1180:507] str : Hello World
2015-10-06 18:44:04.500 a.out[1180:507] str : Hello World Octopus
2015-10-06 18:44:04.500 a.out[1180:507] str : Hello Insert World Octopus
2015-10-06 18:44:04.501 a.out[1180:507] str : Hello sert World Octopus
2015-10-06 18:44:04.501 a.out[1180:507] str : Hello Replace d Octopus

二. 日期 时间 API

1. 日期 时间 示例

示例源码 ​: 

/*************************************************************************
> File Name: OCNSDateTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 21:12:10 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
//当前时间
NSDate * date = [NSDate date];
NSLog(@"date : %@", date);

//一天后的时间
NSDate * date1 = [[NSDate alloc] initWithTimeIntervalSinceNow : 3600 * 24];
NSLog(@"date1 : %@", date1);

//3天前时间
NSDate * date2 = [[NSDate alloc] initWithTimeIntervalSinceNow : -3 * 3600 * 24];
NSLog(@"date2 : %@", date2);

//获取从 1970年1月1日 开始 20年后的日期
NSDate * date3 = [NSDate dateWithTimeIntervalSince1970 : 3600 * 24 * 366 * 20];
NSLog(@"date3 : %@", date3);

//获取当前 Local 下对应的字符串
NSLocale * cn = [NSLocale currentLocale];
NSLog(@"date1 : %@", [date1 descriptionWithLocale : cn]);

//日期比较
NSDate * date_earlier = [date earlierDate : date1];
NSDate * date_later = [date laterDate : date1];
NSLog(@"date_earlier : %@, date_later : %@", date_earlier, date_later);

//比较结果 枚举值 之前 NSOrderAscending 相同 NSOrderdSame 之后 NSOrderdDescending
switch ([date compare : date1])
{
case NSOrderedAscending :
NSLog(@"NSOrderedAscending");
break;
case NSOrderedSame :
NSLog(@"NSOrderedSame");
break;
case NSOrderedDescending :
NSLog(@"NSOrderedDescending");
break;
}

//比较时间差
NSLog(@"date - date1 : %g second", [date timeIntervalSinceDate : date1]);
NSLog(@"date - now : %g second", [date timeIntervalSinceNow]);
}
}

-- ​执行结果 ​: 

bogon:~ octopus$ clang -fobjc-arc -framework Foundation OCNSDateTest.m 
bogon:~ octopus$ ./a.out
2015-10-06 21:45:23.441 a.out[1400:507] date : 2015-10-06 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date1 : 2015-10-07 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date2 : 2015-10-03 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date3 : 1990-01-16 00:00:00 +0000
2015-10-06 21:45:23.444 a.out[1400:507] date1 : 2015年10月7日 星期三 中国标准时间下午9:45:23
2015-10-06 21:45:23.444 a.out[1400:507] date_earlier : 2015-10-06 13:45:23 +0000, date_later : 2015-10-07 13:45:23 +0000
2015-10-06 21:45:23.445 a.out[1400:507] NSOrderedAscending
2015-10-06 21:45:23.445 a.out[1400:507] date - date1 : -86400 second
2015-10-06 21:45:23.445 a.out[1400:507] date - now : -0.011359 second

2. 日期格式器

(1) NSDateFormatter 作用

NSDateFormatter 作用​ : 使 NSDate 与 NSString 对象之间相互转化;

NSString 与 NSDate 转换步骤​ : 

-- ​1.创建 NSDateFormatter 对象​ : 

-- ​2.设置格式​ : 调用 NSDateFormatter 的 "setDateStyle :", "setTimeStyle :" 方法设置时间日期格式;

-- ​3. NSDate -> NSString​ : 调用 NSDateFormatter 的 "stringFromDate :" 方法;

-- ​4. NSString -> NSDate​ : 调用 NSDateFormatter 的 "dateFromString :" 方法;

(2) NSDateFormatter 时间日期格式

时间 日期格式 枚举​ : 

-- ​NSDateFormatterNoStyle​ : 不显示日期, 时间;

-- ​NSDateFormatterShortStyle​ : 显示短日期;

-- ​NSDateFormatterMediumStyle​ : 显示中等日期;

-- ​NSDateFormatterLongStyle​ : 显示长日期;

-- ​NSDateFormatterFullStyle​ : 显示完整日期;

-- ​自定义模板​ : 调用 NSDateFormatter 的 "setDateFormat :" 方法 设置 时间 日期格式;

(3) NSDateFormatter 代码示例

示例代码​ : 

/*************************************************************************
> File Name: OCNSDateFormatterTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 三 10/ 7 14:10:32 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
//创建日期
NSDate * date = [NSDate date];

//初始化 Locale 信息
NSLocale * cn = [[NSLocale alloc] initWithLocaleIdentifier : @"zh_CN"];
NSLocale * en = [[NSLocale alloc] initWithLocaleIdentifier : @"en_US"];

//创建并设置 NSDateFormatter
NSDateFormatter * style_short = [[NSDateFormatter alloc] init];
[style_short setDateStyle : NSDateFormatterShortStyle];

NSDateFormatter * style_medium = [[NSDateFormatter alloc] init];
[style_medium setDateStyle : NSDateFormatterMediumStyle];

NSDateFormatter * style_long = [[NSDateFormatter alloc] init];
[style_long setDateStyle : NSDateFormatterLongStyle];

NSDateFormatter * style_full = [[NSDateFormatter alloc] init];
[style_full setDateStyle : NSDateFormatterFullStyle];

//打印中国格式的日期信息
NSLog(@"cn short date : %@", [style_short stringFromDate : date]);
NSLog(@"cn medium date : %@", [style_medium stringFromDate : date]);
NSLog(@"cn long date : %@", [style_long stringFromDate : date]);
NSLog(@"cn full date : %@", [style_full stringFromDate : date]);

//将四个 NSDateFormatter 设置成美国格式
[style_short setLocale : en];
[style_medium setLocale : en];
[style_long setLocale : en];
[style_full setLocale : en];

//打印美国格式的日期字符串
NSLog(@"en short date : %@", [style_short stringFromDate : date]);
NSLog(@"en medium date : %@", [style_medium stringFromDate : date]);
NSLog(@"en long date : %@", [style_long stringFromDate : date]);
NSLog(@"en full date : %@", [style_full stringFromDate : date]);
}
}

-- ​执行结果​ : 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSDateFormatterTest.m 
localhost:oc_object octopus$ ./a.out
2015-10-07 18:54:08.207 a.out[825:507] cn short date : 15-10-7
2015-10-07 18:54:08.209 a.out[825:507] cn medium date : 2015年10月7日
2015-10-07 18:54:08.209 a.out[825:507] cn long date : 2015年10月7日
2015-10-07 18:54:08.210 a.out[825:507] cn full date : 2015年10月7日 星期三
2015-10-07 18:54:08.211 a.out[825:507] en short date : 10/7/15
2015-10-07 18:54:08.212 a.out[825:507] en medium date : Oct 7, 2015
2015-10-07 18:54:08.212 a.out[825:507] en long date : October 7, 2015
2015-10-07 18:54:08.213 a.out[825:507] en full date : Wednesday, October 7, 2015

3. 日历 (NSCalendar) 日期 (NSDateComponents) 组件

(1) 两个类简介

NSCalendar 与 NSDateComponents 简介​ : 

-- ​主要作用​ : 月, 日, 年 等数值转化为 NSDate, 从 NSDate 对象中提取 月, 日, 年 数值;

-- ​NSCalendar 作用 ​: NSDate 与 NSDateComponents 转化媒介;

-- ​NSDateComponents 作用​ : 专门封装 年月日时分秒 个字段信息, 包含了 year, month, day, hour, minute, second, week, weekday 等 字段的 getter 和 setter 方法;

(2) NSCalendar 常用方法

NSCalendar 常用方法​ : 

--​ NSDate -> 数据​ : "(NSDateComponents *) components : FromDate :", 从 NSDate 中提取 年月日时分秒 各个字段数据;

-- ​数据 -> NSDate​ : "dateFromComponents : (NSDateComponents *) comps", 使用 年月日时分秒 数据创建 NSDate;

(3) 获取 NSDate 中数据

NSDate 获取 日期数值数据​ : 

-- ​1.创建 NSCalendar 对象​ : 

-- 2.​获取 NSDateComponents 对象 ​: 调用 NSCalendar 的 "components : fromDate :" 方法获取 NSDateComponents 对象;

-- ​3.获取具体数值​ : 调用 NSDateComponents 对象的 getter 方法获取各字段具体数值;

(4) 获取 NSDate 中的数值数据

根据 日志数值数据 创建 NSDate ​: 

-- ​1.创建 NSCalendar 对象​ : 

-- ​2.创建 NSDateComponents 对象​ : 调用对象的 setter 方法, 将具体的数值设置到字段中去;

-- ​3.创建 NSDate 对象​ : 调用 NSCalendar 的 "dateFromComponents : (NSDateComponents *)" 初始化 NSDate 对象;

(5) NSCalendar 和 NSDateComponents 示例代码

示例代码​ : 

//
// main.m
// 01.Calendar
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 Calendar 对象
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier : NSGregorianCalendar];
//获取当前日期
NSDate * date = [NSDate date];
//指定 NSDateComponents 中含有的字段信息
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekCalendarUnit;
//获取 NSDateComponents 对象
NSDateComponents * components = [calendar components:unitFlags fromDate:date];
//将 NSDateComponents 对象中得字段打印出来
NSLog(@"%ld 年 %ld 月 %ld 日, %ld 时, %ld 分, %ld 秒, 星期 %ld", components.year, components.month, components.day, components.hour, components.minute, components.second, components.weekday);

//根据 NSDateComponents 创建 NSDate 对象
components.year = 3000;
NSDate * date1 = [calendar dateFromComponents:components];
NSLog(@"date1 : %@", date1);
}

}

-- ​执行结果​ : 

2015-10-08 09:56:28.695 01.Calendar[1255:303] 2015 年 10 月 8 日, 9 时, 56 分, 28 秒, 星期 9223372036854775807
2015-10-08 09:56:28.701 01.Calendar[1255:303] date1 : 3000-10-08 01:56:28 +0000
Program ended with exit code: 0

4. 定时器

(1) 定时器创建

创建定时器​ : 

-- ​两个创建方法​ : 调用 NSTimer 的 "scheduledTimeWithTimeInterval : repeats : " 方法, 或者 scheduledTimerWithTimeInterval : target : selector : userInfo : repeats : " 方法;

-- ​timeInterval 参数​ : 指定执行周期, 每隔多少时间执行一次;

-- ​target 与 selector 参数​ : 指定重复执行任务, 如果指定 target 或者 selector 参数, 则指定使用 target 的 selector 方法为执行的任务;

-- ​Invocation 参数​ : 传入一个 NSInvocation 对象, 该 NSInvocation 对象也是封装了一个 target 和 selector;

-- ​userInfo 参数​ : 传入额外的附加信息;

-- ​repeats 参数​ : 指定一个 BOOL 值, 指定是否需要循环执行任务;

(2) 定时器流程

定时器使用流程​ : 

-- ​创建定时器​ : 

[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:NSSelectorFromString(@"info:")
userInfo:nil
repeats: YES];

-- ​编写任务方法​ : 

-- ​销毁定时器​ :

[timer invalidate];


三. 对象拷贝

1. 拷贝方法 copy 与 mutableCopy

(1) 方法简介

拷贝方法简介​  : 

-- ​copy 方法​ : 复制对象的副本, 一般返回对象不可修改的副本; 假如被复制的对象是可修改的 NSMutableString, 复制后成为 NSString 不可修改;

-- ​mutableCopy 方法​ : 复制对象的可变副本, 返回对象的可变副本; 假如被复制对象不可修改 如 NSString, 使用该方法复制后为 NSMutableString 可以修改;

(2) 示例代码

示例代码​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSString * str = @"octopus";
NSMutableString * str_mutable = [NSMutableString stringWithString:@"octopus"];

//复制可变字符串
NSMutableString * str_mutable1 = [str mutableCopy];
NSMutableString * str_mutable2 = [str_mutable mutableCopy];

//验证可变字符串
[str_mutable1 appendString:@" mutable"];
[str_mutable2 appendString:@" mutable"];
NSLog(@"str_mutable1 : %@, str_mutable2 : %@", str_mutable1, str_mutable2);

//复制不可变字符串
NSString * str1 = [str copy];
NSMutableString * str2 = [str_mutable copy];
[str2 appendString:@" mutable"];
NSLog(@"str_mutable2 : %@", str_mutable2);
}
return 0;
}

-- ​执行结果​ : 后面的复制 不能被修改, 所以报错;

2015-10-08 20:14:57.690 03.Copy[760:303] str_mutable1 : octopus mutable, str_mutable2 : octopus mutable
2015-10-08 20:14:57.692 03.Copy[760:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8fda225c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e6a0e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8fda210c +[NSException raise:format:] + 204
3 CoreFoundation 0x00007fff8fd71dbe mutateError + 110
4 03.Copy 0x0000000100000dfc main + 348
5 libdyld.dylib 0x00007fff84bb85fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

2. 自定义 拷贝方法

(1) 自定义类拷贝方法

调用 copy 方法前提​ : 

-- ​1.该类实现了 NSCopying 协议​;

-- ​2.该类实现了 copyWithZone: 方法​;

调用 mutableCopy 方法前提​ : 

-- ​1.该类实现了 NSMutableCopying 协议​;

-- ​2.该类实现了 mutableCopyWithZone 方法​;

(2) 代码示例

自定义类赋值代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, strong) NSString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone]init];
cat.name = self.name;
cat.age = self.age;
return cat;
}


@end

-- ​main.m​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
cat2.name = [NSMutableString stringWithString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}

-- ​执行结果​ : 

2015-10-08 20:41:08.584 03.Copy[941:303] cat1.name : Cat One, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

3. 浅复制 深复制

(1) 浅拷贝示例

浅拷贝示例​ : 复制 cat2 对象是从 cat1 复制而来, 但是 cat1 中得 name 是一个 NSString * 引用对象, 这两个 cat1 cat2 都指向同一个 name 对象;

-- ​修改下之前的 main 函数​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
[(NSMutableString *)cat2.name replaceCharactersInRange:NSMakeRange(0, 7) withString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}

-- ​执行结果​ : 

2015-10-09 17:13:56.329 03.Copy[1744:303] cat1.name : Cat Two, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

(2) 深拷贝示例

深拷贝完整示例​ : 

-- ​OCCat.h​ : 与之前的相同;

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, strong) NSString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m ​: 只是在 copyWithZone 方法中, 将 name 赋值 改为 name copy 后赋值;

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone]init];
cat.name = [self.name mutableCopy];
cat.age = self.age;
return cat;
}


@end

-- ​main.m​ : 与之前相同;

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
[(NSMutableString *)cat2.name replaceCharactersInRange:NSMakeRange(0, 7) withString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}

-- ​执行结果​ : 

2015-10-09 17:27:22.302 03.Copy[1809:303] cat1.name : Cat One, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

4. setter 的 copy 参数

(1) copy 参数

copy 参数用处 ​: 

-- ​示例​ : 

@property (nonatomic, copy) NSMutableString * name;

-- ​作用​ : 为 name 属性 赋值时, 将赋值对象 copy 一份, 将副本赋值给 name 属性;

-- ​使用 copy 指令, 相当于将 setter 方法设置成如下状态​ : 

- (void) setName:(NSMutableString *)name1
{
this.name = [name1 copy];
}

(2) copy 参数示例

copy 代码错误使用示例 ​: copy 的属性, 赋值后 是不可变的, 如 NSMutableString 接收一个 NSString 赋值, 如果在对赋值后的属性执行 NSMutableString 的操作, 就会报错;

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSMutableString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

@end

-- ​main.h ​:

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

[cat1.name appendString:@" append"];
}
return 0;
}

-- ​执行结果​ : 

2015-10-09 23:17:01.469 03.Copy[2095:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8fda225c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e6a0e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8fda210c +[NSException raise:format:] + 204
3 CoreFoundation 0x00007fff8fd71dbe mutateError + 110
4 03.Copy 0x0000000100000d86 main + 246
5 libdyld.dylib 0x00007fff84bb85fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

四. NSArray NSMutableArray 数组集合

Objective-C 集合概述​ : 

-- ​NSArray​ : 有序, 可重复集合;

-- ​NSSet​ : 无序, 不可重复集合;

-- ​NSDictionary​ : 有映射关系的集合;

1. NSArray 基本功能用法

(1) NSArray 创建

NSArray 简介​ : 有序, 可重复集合;

-- ​特点​ : 每个元素都有对应的顺序索引, 允许重复元素, 通过索引来访问指定位置元素, 索引从 0 开始;

NSArray 对象创建​ : 

-- ​"array" 方法​ : 创建空得 NSArray 对象;

-- ​"arrayWithContentsOfFile : " 方法​ : 读取文件内容创建 NSArray 对象;

-- ​"initWithContentsOfFile : " 方法​ :  读取文件内容创建 NSArray 对象;

-- ​"arrayWithObject : " 方法​ : 创建只包含单个元素的 NSArray 对象;

-- ​"initWithObject : " 方法​ : 创建只包含单个元素的 NSArray 对象;

-- ​"arrayWithObjects : " 方法​ : 创建包含 N 个元素的 NSArray 对象, 最后一个 nil 元素, 表示 NSArray 集合结束;

NSArray * array = [NSArray arrayWithObjects:@"Smoke", @"Drink", @"Perm", nil];

-- ​"initWithObjects : " 方法​ : 创建包含 N 个元素的 NSArray 对象;

(2) NSArray 基本方法

NSArray 集合主要方法​ : 

-- ​查索引​ : 查询集合元素在 NSArray 中索引;

//获取元素在集合中得位置
NSLog(@"Index Of Drink at subArray is : %ld", [subArray indexOfObject:@"Drink"]);
NSLog(@"Index Of Drink at array is : %ld", [array indexOfObject:@"Drink" inRange:NSMakeRange(1, 2)]);

-- ​查元素​ : 根据索引值 取出 NSArray 集合中得元素;

// 获取 第 0 1 最后一个元素 并打印
NSLog(@"First : %@", [array objectAtIndex:0]);
NSLog(@"Second : %@", [array objectAtIndex:1]);
NSLog(@"Last : %@", [array lastObject]);

-- ​整体调用​ : 对集合元素整体调用的方法;

-- ​排序 ​: 对 NSArray 集合进行排序;

-- ​截取元素​ : 取出 NSArray 部分元素组成新集合;

//截取 1 2 个元素组成新 NSArray 集合对象
NSArray * subArray = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];

-- ​追加元单个素​ : "arrayByAddingObject : " 追加单个元素;

array = [array arrayByAddingObject:@"Run"];

-- ​追加数组​ : "arrayWithObjects : " 追加一个数组;

array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"Jump", @"Fuck", nil]];

(3) NSArray 基本方法 示例代码

示例代码​ : 

-- ​OCCat.h ​: 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 NSArray 对象
NSArray * array = [NSArray arrayWithObjects:@"Smoke", @"Drink", @"Perm", nil];

// 获取 第 0 1 最后一个元素 并打印
NSLog(@"First : %@", [array objectAtIndex:0]);
NSLog(@"Second : %@", [array objectAtIndex:1]);
NSLog(@"Third: %@", array[2]);
NSLog(@"Last : %@", [array lastObject]);

// 打印整个 array
NSLog(@"array : \n%@", array);

//截取 1 2 个元素组成新 NSArray 集合对象, NSIndexSet 集合用于保存索引值
NSArray * subArray = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];

//获取元素在集合中得位置
NSLog(@"Index Of Drink at subArray is : %ld", [subArray indexOfObject:@"Drink"]);
NSLog(@"Index Of Drink at array is : %ld", [array indexOfObject:@"Drink" inRange:NSMakeRange(1, 2)]);

//添加单个元素
array = [array arrayByAddingObject:@"Run"];
//追加一个 NSArray 集合, nil 结尾表示 NSArray 结束
array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"Jump", @"Fuck", nil]];
//遍历 array
for (int i = 0; i < array.count; i ++) {
NSLog(@"array %d : %@", i, [array objectAtIndex:i]);
}

//将字符串写出到文件中
[array writeToFile:@"array.txt" atomically:YES];

//创建 OCCat 的 array
NSArray * array2 = [NSArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age : 20],
nil];
//打印 array, 验证 重写的 description 方法
NSLog(@"array2 is : \n%@", array2);
OCCat* cat = [[OCCat alloc] initWithName : @"Tom" age : 18];
//获取 元素 在 array 中的位置, 验证 isEqual 方法
NSUInteger index = [array2 indexOfObject:cat];
NSLog(@"index Of Tom is : %ld", index);


}
return 0;
}

-- ​执行结果​ : 

2015-10-14 17:16:12.748 04.NSArray[7155:303] First : Smoke
2015-10-14 17:16:12.750 04.NSArray[7155:303] Second : Drink
2015-10-14 17:16:12.751 04.NSArray[7155:303] Third: Perm
2015-10-14 17:16:12.751 04.NSArray[7155:303] Last : Perm
2015-10-14 17:16:12.751 04.NSArray[7155:303] array :
(
Smoke,
Drink,
Perm
)
2015-10-14 17:16:12.752 04.NSArray[7155:303] Index Of Drink at subArray is : 0
2015-10-14 17:16:12.752 04.NSArray[7155:303] Index Of Drink at array is : 1
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 0 : Smoke
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 1 : Drink
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 2 : Perm
2015-10-14 17:16:12.754 04.NSArray[7155:303] array 3 : Run
2015-10-14 17:16:12.754 04.NSArray[7155:303] array 4 : Jump
2015-10-14 17:16:12.755 04.NSArray[7155:303] array 5 : Fuck
2015-10-14 17:16:12.769 04.NSArray[7155:303] array2 is :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>"
)
2015-10-14 17:16:12.769 04.NSArray[7155:303] index Of Tom is : 0
Program ended with exit code: 0

2. NSArray 集合整体调用

(1) NSArray 整体元素调用简介

调用所有元素方法​ : 

-- ​"makeObjectPerformSelector : " 方法​ : 按顺序 依次 调用 NSArray 中集合的每个元素, 需要传入 SEL 参数, 该参数指定需要调用的方法;

-- ​"makeObjectPerformSelector : withObject : " 方法​ : 参数一 SEL 代表的方法, 参数二 方法的参数, 参数三 控制是否终止迭代;

-- ​"enumerateObjectsUsingBlock : " 方法​ : 遍历集合中元素, 使用 集合中的元素 执行指定代码块;

-- ​"enumerateObjectsWithOptions : usingBlock : " 方法​ : 遍历元素, 依次使用元素执行代码块, 可以额外传入一个参数控制遍历选项;

-- ​"enumerateObjectsAtIndexs : options : usingBlock : " 方法​ : 遍历指定范围元素, 依次使用元素执行代码块, 传入最后的参数用于控制遍历; 

(2) NSArray 整体元素调用代码示例

代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 OCCat 的 array
NSArray * array = [NSArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age : 20],
nil];

NSLog(@"array is : \n%@", array);

[array makeObjectsPerformSelector:@selector(purr:) withObject:@" FUCK YOU "];


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 10:50:49.902 04.NSArray[8086:303] array is : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>"
)
2015-10-15 10:50:49.905 04.NSArray[8086:303] cat name : Tom, age 18 is purr
2015-10-15 10:50:49.905 04.NSArray[8086:303] cat name : Jerry, age 20 is purr
Program ended with exit code: 0

3. NSArray 排序

(1) NSArray 排序简介

NSArray 排序​ : 

-- ​"sortArrayUsingFunction : context : " 方法​ : 使用排序函数对集合进行排序, 函数会返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时会返回一个 排序号的 NSArray 集合;

-- ​"sortArrayUsingSelector : " 方法​ : 使用集合元素自身的方法对集合进行排序, 该方法返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时还会返回一个 排序号的 NSArray 集合;

-- ​"sortArrayUsingComparator : " 方法​ : 使用代码块对集合进行排序, 代码块 返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时返回排序号的 NSArray 集合;

(2) NSArray 排序代码示例

NSArray 排序示例代码​ : 

-- ​main.c​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

NSInteger intSort(id num1, id num2, void * context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];

if(v1 < v2)
{
return NSOrderedAscending;
}

if(v1 > v2)
{
return NSOrderedDescending;
}

return NSOrderedSame;
}

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//使用 compare 方法进行排序
array = [array sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"array sort : \n%@\n", array);

//创建一个 NSNumber 元素的 NSarray 集合
NSArray * array_num = [NSArray arrayWithObjects:
[NSNumber numberWithInt:18],
[NSNumber numberWithInt:16],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:-1],
nil];
NSLog(@"array_num : \n%@\n", array_num);

//使用 intSort 方法进行排序
array_num = [array_num sortedArrayUsingFunction:intSort context:nil];
NSLog(@"array_num sort : \n%@\n", array_num);

//使用代码块进行排序
array_num = [array_num sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
if([obj2 intValue] < [obj1 intValue])
{
return NSOrderedAscending;
}

if([obj2 intValue] > [obj1 intValue])
{
return NSOrderedDescending;
}

return NSOrderedSame;
}];
NSLog(@"array_num : \n%@\n", array_num);


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 11:52:51.335 04.NSArray[8465:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 11:52:51.336 04.NSArray[8465:303] array sort :
(
Fuck,
Jerry,
Tom
)
2015-10-15 11:52:51.337 04.NSArray[8465:303] array_num :
(
18,
16,
20,
"-1"
)
2015-10-15 11:52:51.337 04.NSArray[8465:303] array_num sort :
(
"-1",
16,
18,
20
)
2015-10-15 11:52:51.338 04.NSArray[8465:303] array_num :
(
20,
18,
16,
"-1"
)
Program ended with exit code: 0

4. NSArray 枚举器遍历

(1) NSArray 获取枚举器

NSArray 枚举器 NSEnumerator 简介​ : 

-- ​"objectEnumerator : " 方法​ : 返回 NSArray 集合顺序枚举器;

-- ​"reverseObjectEnumerator : "  方法​ : 返回 NSArray 集合的逆序枚举器;

(2) NSEnumerator 枚举器

NSEnumerator 方法简介​ : 

-- ​"allObjects : " 方法​ : 获取集合中的所有元素;

-- ​"nextObjects : " 方法​ : 获取集合中的下一个元素;

(3) NSEnumerator 枚举器示例代码

NSEnumerator 示例代码​ : 

-- ​main.m 代码​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//顺序枚举
NSEnumerator * enumerator = [array objectEnumerator];
id object;
while (object = [enumerator nextObject]) {
NSLog(@"%@", object);
}

NSLog(@"\n");

//逆序枚举
NSEnumerator * reverseEnumerator = [array reverseObjectEnumerator];
while (object = [reverseEnumerator nextObject]) {
NSLog(@"%@", object);
}


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:09:59.170 04.NSArray[8590:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 12:09:59.176 04.NSArray[8590:303] Tom
2015-10-15 12:09:59.177 04.NSArray[8590:303] Jerry
2015-10-15 12:09:59.177 04.NSArray[8590:303] Fuck
2015-10-15 12:09:59.178 04.NSArray[8590:303]
2015-10-15 12:09:59.178 04.NSArray[8590:303] Fuck
2015-10-15 12:09:59.178 04.NSArray[8590:303] Jerry
2015-10-15 12:09:59.179 04.NSArray[8590:303] Tom
Program ended with exit code: 0

5. NSArray 快速枚举

(1) NSArray 快速枚举

快速枚举简介​ : 快速枚举无需获取集合长度, 也不用根据索引访问集合元素;

-- ​语法​ : 

for (id object in array)
{
//对 object 进行操作
}

(2) NSArray 快速枚举示例

NSArray 快速枚举示例​ : 

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//快速枚举
for(id object in array)
{
NSLog(@"%@", object);
}


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:17:36.096 04.NSArray[8642:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 12:17:36.098 04.NSArray[8642:303] Tom
2015-10-15 12:17:36.098 04.NSArray[8642:303] Jerry
2015-10-15 12:17:36.099 04.NSArray[8642:303] Fuck
Program ended with exit code: 0

6. NSMutableArray 可变数组

(1) NSMutableArray 简介

NSMutableArray 简介​ : 

-- ​NSMutableArray 与 NSArray 对比​ : NSArray 是不可变数组, 一旦创建不能增删替换元素, NSMutableArray 可以随时增加 删除 替换 元素;

-- ​"addXX" 方法​ : 添加集合元素的方法;

-- ​"removeXX" 方法​ : 删除集合元素的方法;

-- ​"replaceXX" 方法​ : 替换集合元素的方法;

-- ​"sortXX" 方法​ : 对集合本身排序的方法; 

(2) NSMutableArray 代码示例

NSMutableArray 代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{


@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age: 20],
[[OCCat alloc] initWithName : @"Jay" age : 180],
nil];
NSLog(@"array 原始数组 : \n%@\n", array);

//添加单个元素
[array addObject:[[OCCat alloc] initWithName:@"octopus" age:26]];
NSLog(@"array 追加单个元素 : \n%@\n", array);

//添加数组
[array addObjectsFromArray:[NSArray arrayWithObjects:
[[OCCat alloc] initWithName:@"HanShuliang" age:26],
[[OCCat alloc] initWithName:@"Bill" age:60],
nil]];
NSLog(@"array 追加集合 : \n%@\n", array);

//插入单个元素
[array insertObject : [[OCCat alloc] initWithName:@"Green" age:26] atIndex:0];
NSLog(@"array 插入单个元素 : \n%@\n", array);

//插入集合
[array insertObjects: [NSArray arrayWithObjects:
[[OCCat alloc] initWithName:@"LiKeqiang" age:26],
[[OCCat alloc] initWithName:@"Son" age:60],
nil]
atIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)]];
NSLog(@"array 插入集合 : \n%@\n", array);

//删除最后一个元素
[array removeLastObject];
NSLog(@"array 删除最后一个元素 : \n%@\n", array);

//删除第3个元素
[array removeObjectAtIndex:3];
NSLog(@"array 删除第三个元素 : \n%@\n", array);

//删除第3,4个元素
[array removeObjectsInRange:NSMakeRange(3, 2)];
NSLog(@"array 删除第3,4个元素 : \n%@\n", array);

//替换第0个元素
[array replaceObjectAtIndex:0 withObject:[[OCCat alloc] initWithName:@"HanShuliang" age:28]];
NSLog(@"array 替换第0个元素 : \n%@\n", array);




}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:51:43.749 04.NSArray[9033:303] array 原始数组 : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>"
)
2015-10-15 12:51:43.752 04.NSArray[9033:303] array 追加单个元素 :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>"
)
2015-10-15 12:51:43.752 04.NSArray[9033:303] array 追加集合 :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.753 04.NSArray[9033:303] array 插入单个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.753 04.NSArray[9033:303] array 插入集合 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Son, age = 60]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.755 04.NSArray[9033:303] array 删除最后一个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Son, age = 60]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.756 04.NSArray[9033:303] array 删除第三个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.757 04.NSArray[9033:303] array 删除第3,4个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.757 04.NSArray[9033:303] array 替换第0个元素 :
(
"<OCCat [name = HanShuliang, age = 28]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
Program ended with exit code: 0

7. NSArray 的 KVO KVC 用法

(1) NSArray KVC 简介

NSArray KVC 简介​ : NSArray 可以对元素进行整体 KVC 编码;

-- ​"setValue : forKey : " 方法​ : 将所有元素的制定 key 变量设置为 某个值;

-- ​"valueForKey : " 方法​ : 返回 所有元素指定变量值组成的 NSArray 集合;

(2) NSArray KVO 简介

NSArray KVO 简介​ : NSArray 中可以对所有元素进行 KVO 编程;

-- ​"addObserver : forKeyPath : options : context : " 方法 ​: 为集合中所有元素添加 KVO 监听器;

-- ​"removeObserver : forKeyPath : " 方法​ : 为集合中所有元素删除 KVO 监听器;

-- ​"addObserver : toObjectAtIndexes : forKeyPath : options : context : " 方法​ : 为集合中指定元素添加 KVO 监听;

-- ​"removeObserver : fromObjectsAtIndexes : forKeyPath : " 方法​ : 为集合中指定元素删除 KVO 监听;

(3) NSArray KVC KVO 示例代码

NSArray KVC KVO 示例代码​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m ​: 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

--​ main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{


@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age: 20],
[[OCCat alloc] initWithName : @"Jay" age : 180],
nil];
NSLog(@"array 原始数组 : \n%@\n", array);

NSArray * str_array = [array valueForKeyPath:@"name"];
NSLog(@"str_array : \n%@\n", str_array);

[array setValue:@"octopus" forKeyPath:@"name"];
NSLog(@"array 设置 KVC 后的数组 : \n%@\n", array);




}
return 0;
}

-- ​执行结果​ : 

2015-10-15 13:07:04.116 04.NSArray[9135:303] array 原始数组 : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>"
)
2015-10-15 13:07:04.118 04.NSArray[9135:303] str_array :
(
Tom,
Jerry,
Jay
)
2015-10-15 13:07:04.118 04.NSArray[9135:303] array 设置 KVC 后的数组 :
(
"<OCCat [name = octopus, age = 18]>",
"<OCCat [name = octopus, age = 20]>",
"<OCCat [name = octopus, age = 180]>"
)
Program ended with exit code: 0


五. NSSet 与 NSmutableSet 集合


1. NSSet 功能与用法

(1) NSSet 简介

NSSet 功能简介​ : 

-- ​基本属性​ : 无序, 不可重复; 如果将两个相同的元素放在同一个 NSSet 中, 只会保留一个;

-- ​性能分析​ : NSSet 使用 hash 方法存储集合中的元素, 存取 和 查找性能很好;

(2) NSSet 与 NSArray 的相同之处

NSSet 与 NSArray 相同之处​ : 

-- ​获取元素数量​ : 调用 count 方法获取集合元素数量;

-- ​快速枚举​ : 都可以通过 for (id object in collection) 快速枚举来遍历元素;

-- ​枚举器​ : 都可以通过 objectEnumerator 方法获取 NSEnumerator 枚举器对集合元素进行遍历;

-- ​方法遍历​ : 都可以通过 "makeObjectPerformSelector : " 和 "makeObjectPerformSelector : withObject : " 方法对集合元素整体调用某个方法;

-- ​代码块遍历​ : 都可以通过 "enumerateObjectUsingBlock : " 和 "enumerateObjectWithOptions : usingBlock : " 使用代码块遍历执行集合元素;

-- ​KVC 编程​ : 都可以通过 "valueForKey : " 和 "setValue : forKey : " 进行所有元素的 KVC 编程;

-- ​KVO 编程​ : 都可以通过 "addObserver : forKeyPath : options : context : " 等方法进行 KVO 编程; 

(3) NSSet 常用方法

NSSet 常用方法​ : 

-- ​"setByAddingObject : " 方法​ : 向集合中添加一个新元素, 返回新集合;

-- ​"setByAddingObjectFromSet : " 方法​ : 向 NSSet 集合中添加一个 NSSet 集合, 返回新集合;

-- ​"setByAddingObjectFromArray : " 方法​ : 向 NSSet 集合中添加一个 NSArray 集合, 返回新集合;

-- ​"allObjects : " 方法​ : 将 NSSet 集合中所有元素组成 NSArray , 并返回 NSArray 集合;

-- ​"anyObject : " 方法​ : 返回 NSSet 集合中的某个元素;

-- ​"containsObject : " 方法​ : 判断是否包含 某元素;

-- ​"member : "方法​ : 判断是否包含指定元素, 如果包含返回该元素, 否则返回 nil;

-- ​"objectPassingTest : " 方法​ : 使用代码块过滤集合元素, 通过验证的元素组成新的 NSSet 集合并返回该集合;

-- ​"objectWithOptions : passingTest : " 方法​ : 在 "objectPassingTest : " 基础上额外传入一个 NSEnumerationOptions 参数遍历元素; 

-- ​"isSubsetOfSet : " 方法​ : 判断当前 NSSet 集合是否是另外一个集合的子集合;

-- ​"intersectsSet : " 方法​ : 计算两个集合是否有交集;

-- ​"isEqualToSet : " 方法​ : 判断两个集合元素是否相等;

(4) NSSet 代码示例

NSSet 代码示例​ : 

-- ​代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSSet * set = [NSSet setWithObjects:@"Tom", @"Jerry", @"Hank", nil];

//输出集合大小
NSLog(@"set 集合大小 : %ld", [set count]);

NSSet * set1 = [NSSet setWithObjects:@"Angle", @"Devil", nil];
//添加单个元素
set1 = [set1 setByAddingObject:@"Han"];
//添加整个集合
set1 = [set1 setByAddingObjectsFromSet:set];

//输出合并后的 NSSet
NSLog(@"set 与 set1 合并后的 NSSet : \n%@", set1);

//判断交集
BOOL b1 = [set intersectsSet:set1];
NSLog(@"set1 与 set 是否有交集 : %d", b1);

//判断 set 是否是 set1 的子集
BOOL b2 = [set isSubsetOfSet:set1];
NSLog(@"set 是否是 set1 的子集 : %d", b2);

//判断 set 是否包含 Tom 字符串
BOOL b3 = [set containsObject:@"Tom"];
NSLog(@"set 是否包含 Tom : %d", b3);

//过滤
NSSet * set2 = [set1 objectsPassingTest:^BOOL(id obj, BOOL *stop) {
return (BOOL)([obj length] > 4);
}];
NSLog(@"过滤后的 set2 : \n%@", set2);



}
return 0;
}

-- ​执行结果​ : 

2015-10-18 10:49:22.118 05.NSSet[11008:303] set 集合大小 : 3
2015-10-18 10:49:22.120 05.NSSet[11008:303] set 与 set1 合并后的 NSSet :
{(
Hank,
Jerry,
Han,
Devil,
Angle,
Tom
)}
2015-10-18 10:49:22.120 05.NSSet[11008:303] set1 与 set 是否有交集 : 1
2015-10-18 10:49:22.121 05.NSSet[11008:303] set 是否是 set1 的子集 : 1
2015-10-18 10:49:22.121 05.NSSet[11008:303] set 是否包含 Tom : 1
2015-10-18 10:49:22.122 05.NSSet[11008:303] 过滤后的 set2 :
{(
Jerry,
Devil,
Angle
)}
Program ended with exit code: 0

2. NSSet 判重原理

(1) NSSet 重复判定原理

NSSet 添加元素判断​ : 

-- ​位置判断​ : 向 NSSet 中添加元素时, NSSet 会调用对象的 hash 方法 获取对象的 哈希值, 根据 HashCode 判断元素在 NSSet 哈希表中的存储位置;

-- ​重复判断​ : 两个元素 HashCode 相同, 通过 isEqual : 方法判断, 如果返回 NO 则将两个元素放在同一个位置, 如果返回 YES 添加失败;

NSSet 判断元素相同标准​ : 

-- ​值相等​ : 调用 isEqual : 方法返回 YES;

-- ​hashCode 相等​ : 元素的 hash 方法返回值相同;

(2) hash 方法规则

注意 ​: 

-- ​重写对象​ : 如果重写了对象的 isEqual 方法, 其 hash 方法也应该被重写, 尽量保持 isEqual 方法返回 YES 时, hash 方法也返回 YES;

-- ​关于同一位置存储​ : hashCode 相同, isEqual 不同的时候, 同一个位置存储多个元素, 需要用链表连接这些元素, 这会降低 NSSet 访问性能;

hash 方法规则​ : 

-- ​同一对象返回的值相同​;

-- ​isEqual 方法返回值相同时, hash 方法返回的值也应该相同​;

-- ​isEqual 标准的实例变量应该用 hashCode 计算​;

(3) 代码实例

代码实例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSSet * set = [NSSet setWithObjects:
[[OCCat alloc] initWithName:@"Tom" age:18],
[[OCCat alloc] initWithName:@"Jerry" age:20],
[[OCCat alloc] initWithName:@"Tom" age:18],
nil];
NSLog(@"set 集合个数 : %ld \n内容 : \n%@", [set count], set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 12:17:44.740 05.NSSet[11464:303] set 集合个数 : 2 
内容 :
{(
<OCCat [name = Tom, age = 18]>,
<OCCat [name = Jerry, age = 20]>
)}
Program ended with exit code: 0

3. NSMutableSet 功能与用法

(1) NSMutableSet 简介

NSMutableSet 简介​ : NSMutableSet 可以动态添加, 删除, 修改 集合元素, 可计算集合的 交集 并集 差集;

-- ​"addObject : " 方法​ : 向集合中添加单个元素;

-- ​"removeObject : " 方法​ : 从集合中删除单个元素;

-- ​"removeAllObjects" 方法 ​: 删除集合中所有元素;

-- ​"addObjectsFromArray : " 方法​ : 向 NSSet 集合中添加 NSArray 集合中的所有元素;

-- ​"unionSet : " 方法​ : 计算两个 NSSet 并集;

-- ​"minusSet : " 方法​ : 计算两个 NSSet 集合的差集;

-- ​"setSet : " 方法​ : 用一个集合的元素 替换 已有集合的所有的元素;

(2) NSMutableSet 代码示例

NSMutableSet 示例代码​ : 

-- ​示例代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableSet * set = [NSMutableSet setWithCapacity:5];
//添加一个
[set addObject:@"Tom"];
//添加3个 元素 从 NSArray
[set addObjectsFromArray:[NSArray arrayWithObjects:@"Jerry", @"Cat", @"Mouse", nil]];
//去掉一个
[set removeObject:@"Mouse"];
NSLog(@"添加一个 添加 3个 去掉一个后的 set : \n%@", set);

NSSet * set2 = [NSSet setWithObjects:@"Tom", @"Hank", nil];
[set unionSet:set2];
NSLog(@"合集是 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 17:57:14.948 05.NSSet[11656:303] 添加一个 添加 3个 去掉一个后的 set : 
{(
Jerry,
Cat,
Tom
)}
2015-10-18 17:57:14.950 05.NSSet[11656:303] 合集是 :
{(
Jerry,
Cat,
Hank,
Tom
)}
2015-10-18 17:57:14.950 05.NSSet[11656:303] 差集是 :
{(
Jerry,
Cat
)}
Program ended with exit code: 0

4. NSCountedSet 功能与用法

(1) NSCountedSet 简介

NSCountedSet 简介​ : 

-- ​增加元素​ : 该类是 NSMutableSet 的子类, 为每个元素维护了一个 计数 状态, 向该 NSCountedSet 中添加一个元素时, 如果添加成功, 则该元素的添加计数 标注为 1, 如果添加失败, 会再该元素的添加计数 +1; 

-- ​删除元素​ : 从 NSCountedSet 集合中删除元素时, 计数会 -1, 某元素的添加计数减到 0 会删除这个元素;

-- "countForObject : " 方法 : 获取指定元素的添加次数;

(2) NSCountedSet 示例代码

示例代码​ : 

-- ​代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSCountedSet * set = [NSCountedSet setWithObjects:@"Tom", @"Jerry", @"Hank", nil];
[set addObject:@"Tom"];
[set addObject:@"Tom"];

NSLog(@"set : \n%@", set);

[set removeObject:@"Tom"];
NSLog(@"set 删除一次后的效果 : \n%@", set);

[set removeObject:@"Tom"];
[set removeObject:@"Tom"];

NSLog(@"set 删除三次后的效果 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 18:10:56.253 05.NSSet[11746:303] set : 
<NSCountedSet: 0x100200330> (Tom [3], Jerry [1], Hank [1])
2015-10-18 18:10:56.255 05.NSSet[11746:303] set 删除一次后的效果 :
<NSCountedSet: 0x100200330> (Tom [2], Jerry [1], Hank [1])
2015-10-18 18:10:56.255 05.NSSet[11746:303] set 删除三次后的效果 :
<NSCountedSet: 0x100200330> (Jerry [1], Hank [1])
Program ended with exit code: 0

5. NSOrderedSet 与 NSMutableOrderedSet 有序集合

(1) 有序集合简介

NSOrderedSet 简介​ : 

-- ​特点​ : 不允许重复, 可以保持元素添加顺序, 每个元素都有索引, 可以根据索引操作元素;

(2) 有序集合代码示例

有序集合代码示例​ : 

-- ​main.m 代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSOrderedSet * set = [NSOrderedSet orderedSetWithObjects:@"Tom", @"Jerry", @"Hank", nil];

NSLog(@"第1个元素 : %@", [set firstObject]);
NSLog(@"第2个元素 : %@", [set objectAtIndex : 1]);
NSLog(@"最后1个元素 : %@", [set lastObject]);
NSLog(@"Tom 的索引 : %ld", [set indexOfObject : @"Tom"]);

NSIndexSet * index_set = [set indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return (BOOL) ([obj length] > 3);
}];
NSLog(@"%@", index_set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 18:31:30.562 05.NSSet[11925:303] 第1个元素 : Tom
2015-10-18 18:31:30.564 05.NSSet[11925:303] 第2个元素 : Jerry
2015-10-18 18:31:30.565 05.NSSet[11925:303] 最后1个元素 : Hank
2015-10-18 18:31:30.565 05.NSSet[11925:303] Tom 的索引 : 0
2015-10-18 18:31:30.566 05.NSSet[11925:303] <NSIndexSet: 0x100103760>[number of indexes: 2 (in 1 ranges), indexes: (1-2)]
Program ended with exit code: 0

六. NSDictionary 与 NSMutableDictionary 字典集合


1. NSDictionary 功能与用法

(1) NSDictionary 简介

NSDictionary 简介​ : 

-- ​作用 ​: NSDictionary 集合用于保存具有映射关系的数据, 其中保存两组数据, 一组是 key, 一组是 value, key 不允许重复;

-- ​key 与 value 对应关系​ : key 与 value 是一一对应的, 每个 key 都能找到对应的 value;

(2) NSDictionary 方法简介

NSDictionary 创建方法简介​ : 

-- ​"dictionary : " 方法​ : 创建不包含任何 key value 的 NSDictionary 集合;

-- ​"dictionaryWithContentsOfFile : / initWithContentsOfFile : " 方法​ : 读取文件, 使用文件内容生成 NSDictionary 集合, 一般这种文件是从 NSDictionary 集合输出的, 需要有指定的格式;

-- ​"dictionaryWithDictionary : / initWithDictionary : " 方法​ : 使用现有的 NSDictionary 生成新的 NSDictionary;

-- ​"dictionaryWithObject : forKey : " 方法​ : 使用单个 key-value 创建 NSDictionary 集合;

-- ​"dictionaryWithObjects : forKeys : / initWithObjects : forKeys : " 方法​ : 使用两个 NSArray 分别指定 key 和 value 集合;

-- ​"dictionaryWithObjectsAndKeys : / initWithObjectAndKeys : " 方法​ : 调用该方法, 需要按照 key-value 格式传入多个 键值对集合;

(3) NSDictionary 常用方法

NSDictionary 常用方法​ : 

--​ "count : " 方法​ : 返回 NSDictionary 含有的 key-value 的数量;

-- ​"allKeys : " 方法​ : 返回 NSDictionary 集合含有的 key 集合;

-- ​"allKeysForObject : " 方法​ : 返回指定 Value 的全部 key 的集合;

-- ​"allValues : " 方法​ : 该方法返回 NSDictionary 包含的全部 value 集合;

-- ​"objectForKeyedSubscript : " 方法​ : 允许 NSDictionary 通过下标方法获取指定 key 的 value;

-- ​"valueForKey : " 方法​ : 获取 NSDictionary 指定 key 的 value 值;

-- ​"keyEnumerator : " 方法​ : 返回 key 集合的 NSEnumerator 对象;

-- ​"objectEnumerator : " 方法​ : 返回 value 集合的 NSEnumerator 对象;

-- ​"enumerateKeysAndObjectsUsingBlock : " 方法​ : 使用指定的代码块迭代集合中的键值对;

-- ​"enumerateKeysAndObjectsWithOptions : usingBlock : " 方法 ​: 使用指定代码块迭代集合中的键值对, 额外传入一个 NSEnumerationOptions 参数;

-- ​"writeToFile : atomically : " 方法​ : 将 NSDictionary 对象数据写入文件中;

(4) NSDictionary 示例代码

NSDictionary 示例代码​ : 

-- ​NSDictionary+toString.h​ : 

//
// NSDictionary+toString.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSDictionary (toString)
- (void) toString;
@end

-- ​NSDictionary+toString.m​ : 

//
// NSDictionary+toString.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "NSDictionary+toString.h"

@implementation NSDictionary (toString)
- (void) toString
{
NSMutableString * string = [NSMutableString stringWithString:@"{"];

for(id key in self)
{
[string appendString:[key description]];
[string appendString:@" = "];
[string appendString:[self[key] description]];
[string appendString:@" , "];
}

[string appendString:@"}"];
NSLog(@"%@", string);
}
@end

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}
@end

-- ​main.m​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

NSLog(@"dictionary 键值对个数 : %ld", [dictionary count]);

NSLog(@"打印所有 key : \n%@", [dictionary allKeys]);

NSLog(@"打印所有 value : \n%@", [dictionary allValues]);

//枚举器遍历
NSEnumerator * enumerator = [dictionary objectEnumerator];
NSObject * value;
while(value = [enumerator nextObject])
{
NSLog(@"%@", value);
}

//使用代码块遍历 NSDictionary 集合
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

NSLog(@"key : %@ , value : %@", key, obj);
}];



}
return 0;
}

-- 执行结果 : 

2015-10-18 21:49:15.902 06.NSDictionary[12562:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-18 21:49:15.904 06.NSDictionary[12562:303] dictionary 键值对个数 : 3
2015-10-18 21:49:15.904 06.NSDictionary[12562:303] 打印所有 key :
(
Tom,
Jerry,
Hank
)
2015-10-18 21:49:15.905 06.NSDictionary[12562:303] 打印所有 value :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Hank, age = 26]>"
)
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Tom, age = 18]>
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Jerry, age = 20]>
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Hank, age = 26]>
2015-10-18 21:49:15.911 06.NSDictionary[12562:303] key : Tom , value : <OCCat [name = Tom, age = 18]>
2015-10-18 21:49:15.911 06.NSDictionary[12562:303] key : Jerry , value : <OCCat [name = Jerry, age = 20]>
2015-10-18 21:49:15.912 06.NSDictionary[12562:303] key : Hank , value : <OCCat [name = Hank, age = 26]>
Program ended with exit code: 0

2. NSDictionary key 排序

(1) NSDictionary Key 排序简介

NSDictionary 排序方法​ : 

-- ​"keysSortedByValueUsingSelector : " 方法​ : 根据 ​value 指定方法​ 遍历 key-value 键值对, 对 key 排序, ​value 的指定方法必返回 NSOrderedSame, NSOrderedAscending 或 NSOrderedDescending 返回值​; 

-- ​"keysSortedByValueUsingComparator" 方法​ : 根据 ​指定代码块​ 遍历 键值对, 对 key 进行排序, ​代码块方法 需要返回 NSOrderedAscending, NSOrderedDescending 或 NSOrderedSame 返回值​;

-- ​"keysSortedByValueWithOptions : usingComparator : " 方法​ : 与前一个类似, 额外增加了一个 NSEnumerationOptions 参数;

(2) NSDictionary key排序示例代码

NSDictionary Key 排序示例代码​ : 

-- ​OCCat.h​ : 定义 compare : 比较方法;

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
- (NSComparisonResult) compare : (id) other;
@end

-- ​OCCat.m​ : 实现 compare : 比较方法;

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ :  

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

//使用 keysSortedByValueUsingSelector 方法排序
NSArray * array = [dictionary keysSortedByValueUsingSelector:@selector(compare:)];
NSLog(@"array : \n%@", array);

//使用代码块排序
NSArray * array2 = [dictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) {
OCCat * cat1 = (OCCat *)obj1;
OCCat * cat2 = (OCCat *)obj2;
if(cat1.age == cat2.age)
{
return NSOrderedSame;
}

if(cat1.age > cat2.age)
{
return NSOrderedDescending;
}

return NSOrderedAscending;
}];
NSLog(@"array2 : \n%@", array2);

}
return 0;
}

-- ​执行结果​ : 

2015-10-19 12:57:17.276 06.NSDictionary[13537:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-19 12:57:17.279 06.NSDictionary[13537:303] array2 :
(
Tom,
Jerry,
Hank
)
2015-10-19 12:57:17.279 06.NSDictionary[13537:303] array :
(
Tom,
Jerry,
Hank
)
Program ended with exit code: 0

3. NSDictionary key 过滤

(1) NSDictionary Key 过滤方法简介

NSDictionary key 过滤方法简介​ : 

-- ​"keysOfEntriesPassingTest : " 方法 ​: 使用代码块 遍历 键值对, 代码块返回一个 BOOL 值, 参数一 是 key, 参数二 是 value, 第三个是循环标志位;

-- ​"keysOfEntriesWithOptions : passingTest : " 方法​ : 与前一个方法功能基本相同, 增加了 NSEnumerationOptions 参数; 

(2) NSDictionary Key 过滤代码示例

示例代码​ : main.m 不同, 其它代码均相同;

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

NSSet * set = [dictionary keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
OCCat * cat = (OCCat *)obj;
if(cat.age >= 20)
{
return YES;
}
return NO;
}];

NSLog(@"过滤后的key集合 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-19 13:59:42.931 06.NSDictionary[13750:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-19 13:59:42.934 06.NSDictionary[13750:303] 过滤后的key集合 :
{(
Jerry,
Hank
)}
Program ended with exit code: 0

4. 自定义类作为 key

(1) 自定义类为 key 前提

自定义类为 key 基本要求​ : 

-- ​重写isEqual 和 hash 方法​ : isEqual : 和 hash : 方法必须正确重写, 即 isEqual 方法返回 YES 是, hash 方法返回的 hashCode 必须也相同;

-- ​实现 copyWithZone 方法​ : 尽量返回对象的不可变副本; 该策略是出于安全性考虑, 当多个 key-value 放入 NSDictionary 之后, 如果 key 可变导致 key 的hashCode 改变, 就会出现问题; 

(2) 自定义类为 key 代码示例

自定义类为 key 代码​ : 其它类代码相同, 只有 OCCat.m 与 main.m 不同;

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone] init];
cat.name = self.name;
cat.age = self.age;
return cat;
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
@"Tom", [[OCCat alloc] initWithName:@"Tom" age:18],
@"Hank", [[OCCat alloc] initWithName:@"Hank" age:26],
@"Jerry", [[OCCat alloc] initWithName:@"Jerry" age:20],
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 14:09:30.935 06.NSDictionary[15258:303] {<OCCat [name = Tom, age = 18]> = Tom , <OCCat [name = Hank, age = 26]> = Hank , <OCCat [name = Jerry, age = 20]> = Jerry , }
Program ended with exit code: 0

5. NSMutableDictionary 功能与用法

(1) NSMutableDictionary 简介

NSMutableDictionary 独有方法简介​ : 主要是比 NSDictionary 多个 增加 删除 键值对的方法;

-- ​"setObject : forKey : " 方法​ : 设置 key-value 键值对, 如果 key 与之前的不重复, 直接插入, 如果重复, 直接将 value 替换;

-- ​"setObject : forKeyedSubscript : " 方法​ : 通过下标方法设置键值对;

-- ​"addEntriesFromDictionary : " 方法​ : 将另一个 NSDictionary 中的值复制到当前的 NSMutableDictionary 中;

-- ​"setDictionary : " 方法​ : 用一个 NSDictionary 中的所有元素 替换另一个 NSDictionary 中的所有元素;

-- ​"removeObjectForKey : " 方法​ : 根据 key 删除 键值对;

-- ​"removeAllObjects : " 方法​ : 清空 NSDictionary;

-- ​"removeObjectForKeys : " 方法​ : 删除一个 NSArray 中包含的 key 的键值对; 

(2) NSMutableDictionary 方法示例

NSMutableDictionary 示例代码​ : 

-- ​代码​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"Tom", [NSNumber numberWithInt:1],
@"Jerry", [NSNumber numberWithInt:2],
nil];
[dictionary toString];

//替换
NSLog(@"替换");
dictionary[[NSNumber numberWithInt:1]] = @"Hank";
[dictionary toString];

//增加
NSLog(@"增加");
dictionary[[NSNumber numberWithInt:3]] = @"Fuck";
[dictionary toString];

//添加整个字典到另一个字典
NSLog(@"添加整个字典到另一个字典");
NSDictionary * dic1 = [NSDictionary dictionaryWithObjectsAndKeys:
@"Obama", [NSNumber numberWithInt:4],
@"Bush", [NSNumber numberWithInt:5],
nil];
[dictionary addEntriesFromDictionary:dic1];
[dictionary toString];

//删除一部分
NSLog(@"删除一部分");
[dictionary removeObjectsForKeys:[NSArray arrayWithObjects:
[NSNumber numberWithInt:4], [NSNumber numberWithInt:5], nil]];
[dictionary toString];

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 15:04:01.100 06.NSDictionary[15426:303] {1 = Tom , 2 = Jerry , }
2015-10-20 15:04:01.102 06.NSDictionary[15426:303] 替换
2015-10-20 15:04:01.103 06.NSDictionary[15426:303] {1 = Hank , 2 = Jerry , }
2015-10-20 15:04:01.103 06.NSDictionary[15426:303] 增加
2015-10-20 15:04:01.104 06.NSDictionary[15426:303] {3 = Fuck , 1 = Hank , 2 = Jerry , }
2015-10-20 15:04:01.105 06.NSDictionary[15426:303] 添加整个字典到另一个字典
2015-10-20 15:04:01.106 06.NSDictionary[15426:303] {3 = Fuck , 2 = Jerry , 5 = Bush , 1 = Hank , 4 = Obama , }
2015-10-20 15:04:01.106 06.NSDictionary[15426:303] 删除一部分
2015-10-20 15:04:01.107 06.NSDictionary[15426:303] {3 = Fuck , 2 = Jerry , 1 = Hank , }
Program ended with exit code: 0

六. 谓词 NSPredicate


1. 谓词简介

(1) 谓词简介

谓词简介​ : 个人感觉 谓词比较像 Java 中的正则表达式;

-- ​作用​ : 谓词用于定义 逻辑条件, 用于 搜索 或 过滤内存中的数据, 尤其是 搜索过滤集合中的数据;

-- ​NSPredicate 子类​ : NSPredicate 有 3 个子类, NSComparisonPredicate , NSCompoundPredicate, NSExpression;

-- ​创建方法​ : 使用 NSPredicate 的 ​"predicateWithFormat :"​ 方法 创建 NSPredicate 对象;

-- ​没有占位符的谓词结果计算 ​: 直接使用 NSPredicate 的 evalueWithObject 方法计算谓词结果, 返回值是一个 BOOL 值;

-- ​有占位符的谓词结果计算​ : 调用 "predicateWithSubstitutionVariables" 方法为占位符参数设置参数值, 然后执行 evalueWithObject 方法计算结果;

-- ​同时完成两步的方法​ : NSPredicate 提供了一个 "evalueWithObject : substitutionVariables : " 方法可以同时替换占位符 和 计算结果;

(2) 谓词 代码简单示例

谓词代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
- (NSComparisonResult) compare : (id) other;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone] init];
cat.name = self.name;
cat.age = self.age;
return cat;
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ : 其它类 与 NSDictionary 中的示例相同;

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name like 'T*'"];
OCCat * cat = [[OCCat alloc] initWithName:@"Tom" age:18];
OCCat * cat2 = [[OCCat alloc] initWithName:@"Jerry" age:20];

NSLog(@"cat : %d, cat2 : %d", [predicate evaluateWithObject:cat], [predicate evaluateWithObject:cat2]);

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 16:21:32.998 06.NSDictionary[15545:303] cat : 1, cat2 : 0
Program ended with exit code: 0

2. 谓词过滤集合

(1) 集合过滤方法简介

谓词方法简介​ : 谓词遍历集合时, 使用谓词对集合中的元素进行过滤, 元素计算谓词返回 YES 才会被保留下来, 返回 NO, 该元素就会被删除;

-- ​"- (NSArray * ) filteredArrayUsingPredicate : (NSPredicate *) predicate :" 方法 ​: 使用谓词过滤 NSArray 集合, 返回过滤后的新集合;

-- ​"- (void) filterUsingPredicate : (NSPredicate *) predicate :" 方法​ : 使用谓词过滤 NSMutableArray 集合, 直接删除集合中的不合格的元素;

-- ​"- (NSSet * ) filteredSetUsingPredicate : (NSPredicate *) Predicate :" 方法​ : 使用谓词过滤 NSSet 集合, 返回一个新的集合;

-- ​"- (void) filterUsingPredicate : (NSPredicate * ) Predicate :" 方法​ : 过滤 NSMutableSet 集合, 直接删除不合格的元素;

(2) 集合过滤方法代码

示例代码​ : 

-- ​main.c​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[NSNumber numberWithInt:10],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:30],
nil];
//过滤大于 15 的数字
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF > 15"];
[array filterUsingPredicate:predicate];
NSLog(@"过滤后的 array : \n%@", array);

NSSet * set = [NSSet setWithObjects:
[[OCCat alloc] initWithName:@"Tom" age:18],
[[OCCat alloc] initWithName:@"Jerry" age:20],
nil];
//过滤 name 包含 om 字符串的 NSSet
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"name CONTAINS 'om'"];
NSSet * filterSet = [set filteredSetUsingPredicate:predicate1];
NSLog(@"过滤后的 set : \n%@", filterSet);

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 21:17:41.615 06.NSDictionary[15761:303] 过滤后的 array : 
(
20,
30
)
2015-10-20 21:17:41.617 06.NSDictionary[15761:303] 过滤后的 set :
{(
<OCCat [name = Tom, age = 18]>
)}
Program ended with exit code: 0

3. 谓词 占位符

(1) 谓词占位符参数

谓词支持的占位符​ : 

-- ​"%K" 占位符​ : 动态传入属性名;

-- ​"%@" 占位符​ : 动态设置属性值;

动态改变的属性值​ : 

-- ​示例​ : [NSPredicate PredicateWithFormat : @"name CATAINS $JAVA"], $JAVA 是动态改变值, 程序可以动态改变 $JAVA 值;

-- ​设置参数值​ : 调用 NSPredicate 的 predicateWithSubstitutionVariables : 设置参数值, 该方法返回 NSPredicate 对象;

-- ​计算结果​ : 调用 NSPredicate 的 evaluateWithObject : substitutionVariables : 完成参数计算结果;

(2) 谓词占位符参数 代码示例

代码示例 : 

-- main.m : 

-- 执行结果 : 

.

.

.

.

.

.

.

.

.

CocoaChina

Code4App

懒人 IOS 源码库

.



二. 日期 时间 API

1. 日期 时间 示例



四. NSArray NSMutableArray 数组集合


Objective-C 集合概述​ : 


-- ​NSArray​ : 有序, 可重复集合;

-- ​NSSet​ : 无序, 不可重复集合;

-- ​NSDictionary​ : 有映射关系的集合;

1. NSArray 基本功能用法

(1) NSArray 创建



NSDictionary 简介​ : 

-- ​作用 ​: NSDictionary 集合用于保存具有映射关系的数据, 其中保存两组数据, 一组是 key, 一组是 value, key 不允许重复;

-- ​key 与 value 对应关系​ : key 与 value 是一一对应的, 每个 key 都能找到对应的 value;





一. 字符串 API

1. NSString 用法简介

(1) NSString API 介绍

NSString 功能​ : 

-- ​创建字符串​ : 使用 init 开头的实例方法, 也可以使用 String 开头的方法;

// init 开头方法创建字符串
unichar data[5] = {97, 98, 99, 100, 101};
NSString * str = [[NSString alloc] initWithCharacters : data length : 5];
// string 开头方法创建字符串
char * con_str = "Hello World";
NSString * str1 = [NSString stringWithUTF8String : con_str];

-- ​字符串获取​ : 读取文件 或 网络 URL 初始化字符串;

-- ​字符串写出​ : 字符串内容 写入 文件 或 URL;

-- ​长度获取​ : 获取字符串长度, 既可获取字符串内包含的字符个数, 又可获取字符串包含的字节个数;

// 字符串个数 字节数统计
NSLog(@"str char count is : %lu", [str length]);
NSLog(@"str utf8 byte count is : %lu", [str lengthOfBytesUsingEncoding : NSUTF8StringEncoding]);

--​ 获取子字符串​ : 既可以获取指定位置的字符, 又可以获取指定范围的字符串;

// 获取 前 5 个字符组成的字符串
NSString * str5 = [str3 substringToIndex : 5];
// 获取 从 第五个字符开始的字符串
NSString * str6 = [str3 substringFromIndex : 5];
// 获取 从 第五个 到 第九个 字符串
NSString * str7 = [str3 substringWithRange : NSMakeRange(5, 9)];

--​ 获取 C 字符串​ : 获取 NSString * 对应的 char * 字符串;

-- ​连接字符串​ : 将 2 个字符串连接;

//字符串拼接
NSString * str3 = [str2 stringByAppendingString : @", append this"];
NSString * str4 = [str2 stringByAppendingFormat : @", append %@", @"format"];

-- ​分隔字符串​ : 将 一个 字符串分成两个;

-- ​查找 字符 或 子字符串​ : 查找字符串内指定的字符 和 子字符串;

// 获取 "append" 出现的位置
NSRange pos = [str3 rangeOfString : @"append"];
NSLog(@"append position from %ld, length %ld", pos.location, pos.length);

-- ​替换字符串​ : 

-- ​比较字符串​ : 

-- ​字符串大小比较​ : 

-- ​对字符串中得字符进行大小写转换​ : 

// 大小写转换
NSString * str8 = [str2 uppercaseString];
NSLog(@"str8 : %@", str8);

(2) NSString 示例代码

示例代码​ : 

/*************************************************************************
> File Name: OCNSStringDemo.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 17:04:29 2015
************************************************************************/
#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
// init 开头方法创建字符串
unichar data[5] = {97, 98, 99, 100, 101};
NSString * str = [[NSString alloc] initWithCharacters : data length : 5];

// string 开头方法创建字符串
char * con_str = "Hello World";
NSString * str1 = [NSString stringWithUTF8String : con_str];

NSLog(@"str : %@, str1 : %@", str, str1);

// 将字符串写入文件
[str1 writeToFile : @"octopus.txt"
atomically : YES
encoding : NSUTF8StringEncoding
error : nil];

// 从文件读取字符串
NSString * str2 = [NSString stringWithContentsOfFile : @"octopus.txt"
encoding : NSUTF8StringEncoding
error : nil];

NSLog(@"str2 : %@", str2);

//字符串拼接
NSString * str3 = [str2 stringByAppendingString : @", append this"];
NSString * str4 = [str2 stringByAppendingFormat : @", append %@", @"format"];

NSLog(@"str3 : %@, str4 : %@", str3, str4);

// 字符串个数 字节数统计
NSLog(@"str char count is : %lu", [str length]);
NSLog(@"str utf8 byte count is : %lu", [str lengthOfBytesUsingEncoding : NSUTF8StringEncoding]);

// 获取 前 5 个字符组成的字符串
NSString * str5 = [str3 substringToIndex : 5];
// 获取 从 第五个字符开始的字符串
NSString * str6 = [str3 substringFromIndex : 5];
// 获取 从 第五个 到 第九个 字符串
NSString * str7 = [str3 substringWithRange : NSMakeRange(5, 9)];

NSLog(@"str5 : %@, str6 : %@, str7 : %@", str5, str6, str7);

// 获取 "append" 出现的位置
NSRange pos = [str3 rangeOfString : @"append"];
NSLog(@"append position from %ld, length %ld", pos.location, pos.length);

// 大小写转换
NSString * str8 = [str2 uppercaseString];
NSLog(@"str8 : %@", str8);


}
}

-- ​执行结果​ : 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCNSStringDemo.m 
bogon:6.6 octopus$ ./a.out
2015-10-06 17:52:40.007 a.out[1095:507] str : abcde, str1 : Hello World
2015-10-06 17:52:40.018 a.out[1095:507] str2 : Hello World
2015-10-06 17:52:40.018 a.out[1095:507] str3 : Hello World, append this, str4 : Hello World, append format
2015-10-06 17:52:40.019 a.out[1095:507] str char count is : 5
2015-10-06 17:52:40.020 a.out[1095:507] str utf8 byte count is : 5
2015-10-06 17:52:40.020 a.out[1095:507] str5 : Hello, str6 : World, append this, str7 : World, a
2015-10-06 17:52:40.021 a.out[1095:507] append position from 13, length 6
2015-10-06 17:52:40.021 a.out[1095:507] str8 : HELLO WORLD

2. NSMutableString 可变字符串

(1) NSMutableString 简介

NSString 与 NSMutableString 对比​ : 

-- ​NSString 缺陷​ : NSString 字符串一旦被创建, 字符串序列是不可改变的;

-- ​NSMutableString 优点​ : NSString 中所有的方法, NSMutableString 都可以调用, NSMutableString 对象可以当做 NSString 对象使用;

(2) NSMutableString 源码示例

源码示例​ : 

/*************************************************************************
> File Name: OCNSMutableStringTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 18:03:28 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
NSMutableString * str = [NSMutableString stringWithString : @"Hello World"];

NSLog(@"str : %@", str);

// 字符串追加
[str appendString : @" Octopus"];
NSLog(@"str : %@", str);

[str insertString : @"Insert " atIndex : 6];
NSLog(@"str : %@", str);

[str deleteCharactersInRange : NSMakeRange (6, 2)];
NSLog(@"str : %@", str);

[str replaceCharactersInRange : NSMakeRange(6, 9)
withString : @" Replace "];
NSLog(@"str : %@", str);
}
}

-- ​运行结果​ : 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCNSMutableStringTest.m 
bogon:6.6 octopus$ ./a.out
2015-10-06 18:44:04.498 a.out[1180:507] str : Hello World
2015-10-06 18:44:04.500 a.out[1180:507] str : Hello World Octopus
2015-10-06 18:44:04.500 a.out[1180:507] str : Hello Insert World Octopus
2015-10-06 18:44:04.501 a.out[1180:507] str : Hello sert World Octopus
2015-10-06 18:44:04.501 a.out[1180:507] str : Hello Replace d Octopus

二. 日期 时间 API

1. 日期 时间 示例

示例源码 ​: 

/*************************************************************************
> File Name: OCNSDateTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 二 10/ 6 21:12:10 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
//当前时间
NSDate * date = [NSDate date];
NSLog(@"date : %@", date);

//一天后的时间
NSDate * date1 = [[NSDate alloc] initWithTimeIntervalSinceNow : 3600 * 24];
NSLog(@"date1 : %@", date1);

//3天前时间
NSDate * date2 = [[NSDate alloc] initWithTimeIntervalSinceNow : -3 * 3600 * 24];
NSLog(@"date2 : %@", date2);

//获取从 1970年1月1日 开始 20年后的日期
NSDate * date3 = [NSDate dateWithTimeIntervalSince1970 : 3600 * 24 * 366 * 20];
NSLog(@"date3 : %@", date3);

//获取当前 Local 下对应的字符串
NSLocale * cn = [NSLocale currentLocale];
NSLog(@"date1 : %@", [date1 descriptionWithLocale : cn]);

//日期比较
NSDate * date_earlier = [date earlierDate : date1];
NSDate * date_later = [date laterDate : date1];
NSLog(@"date_earlier : %@, date_later : %@", date_earlier, date_later);

//比较结果 枚举值 之前 NSOrderAscending 相同 NSOrderdSame 之后 NSOrderdDescending
switch ([date compare : date1])
{
case NSOrderedAscending :
NSLog(@"NSOrderedAscending");
break;
case NSOrderedSame :
NSLog(@"NSOrderedSame");
break;
case NSOrderedDescending :
NSLog(@"NSOrderedDescending");
break;
}

//比较时间差
NSLog(@"date - date1 : %g second", [date timeIntervalSinceDate : date1]);
NSLog(@"date - now : %g second", [date timeIntervalSinceNow]);
}
}

-- ​执行结果 ​: 

bogon:~ octopus$ clang -fobjc-arc -framework Foundation OCNSDateTest.m 
bogon:~ octopus$ ./a.out
2015-10-06 21:45:23.441 a.out[1400:507] date : 2015-10-06 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date1 : 2015-10-07 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date2 : 2015-10-03 13:45:23 +0000
2015-10-06 21:45:23.442 a.out[1400:507] date3 : 1990-01-16 00:00:00 +0000
2015-10-06 21:45:23.444 a.out[1400:507] date1 : 2015年10月7日 星期三 中国标准时间下午9:45:23
2015-10-06 21:45:23.444 a.out[1400:507] date_earlier : 2015-10-06 13:45:23 +0000, date_later : 2015-10-07 13:45:23 +0000
2015-10-06 21:45:23.445 a.out[1400:507] NSOrderedAscending
2015-10-06 21:45:23.445 a.out[1400:507] date - date1 : -86400 second
2015-10-06 21:45:23.445 a.out[1400:507] date - now : -0.011359 second

2. 日期格式器

(1) NSDateFormatter 作用

NSDateFormatter 作用​ : 使 NSDate 与 NSString 对象之间相互转化;

NSString 与 NSDate 转换步骤​ : 

-- ​1.创建 NSDateFormatter 对象​ : 

-- ​2.设置格式​ : 调用 NSDateFormatter 的 "setDateStyle :", "setTimeStyle :" 方法设置时间日期格式;

-- ​3. NSDate -> NSString​ : 调用 NSDateFormatter 的 "stringFromDate :" 方法;

-- ​4. NSString -> NSDate​ : 调用 NSDateFormatter 的 "dateFromString :" 方法;

(2) NSDateFormatter 时间日期格式

时间 日期格式 枚举​ : 

-- ​NSDateFormatterNoStyle​ : 不显示日期, 时间;

-- ​NSDateFormatterShortStyle​ : 显示短日期;

-- ​NSDateFormatterMediumStyle​ : 显示中等日期;

-- ​NSDateFormatterLongStyle​ : 显示长日期;

-- ​NSDateFormatterFullStyle​ : 显示完整日期;

-- ​自定义模板​ : 调用 NSDateFormatter 的 "setDateFormat :" 方法 设置 时间 日期格式;

(3) NSDateFormatter 代码示例

示例代码​ : 

/*************************************************************************
> File Name: OCNSDateFormatterTest.m
> Author: octopus
> Mail: octopus_truth.163.com
> Created Time: 三 10/ 7 14:10:32 2015
************************************************************************/

#import <Foundation/Foundation.h>

int main(int argc, char * argv[])
{
@autoreleasepool {
//创建日期
NSDate * date = [NSDate date];

//初始化 Locale 信息
NSLocale * cn = [[NSLocale alloc] initWithLocaleIdentifier : @"zh_CN"];
NSLocale * en = [[NSLocale alloc] initWithLocaleIdentifier : @"en_US"];

//创建并设置 NSDateFormatter
NSDateFormatter * style_short = [[NSDateFormatter alloc] init];
[style_short setDateStyle : NSDateFormatterShortStyle];

NSDateFormatter * style_medium = [[NSDateFormatter alloc] init];
[style_medium setDateStyle : NSDateFormatterMediumStyle];

NSDateFormatter * style_long = [[NSDateFormatter alloc] init];
[style_long setDateStyle : NSDateFormatterLongStyle];

NSDateFormatter * style_full = [[NSDateFormatter alloc] init];
[style_full setDateStyle : NSDateFormatterFullStyle];

//打印中国格式的日期信息
NSLog(@"cn short date : %@", [style_short stringFromDate : date]);
NSLog(@"cn medium date : %@", [style_medium stringFromDate : date]);
NSLog(@"cn long date : %@", [style_long stringFromDate : date]);
NSLog(@"cn full date : %@", [style_full stringFromDate : date]);

//将四个 NSDateFormatter 设置成美国格式
[style_short setLocale : en];
[style_medium setLocale : en];
[style_long setLocale : en];
[style_full setLocale : en];

//打印美国格式的日期字符串
NSLog(@"en short date : %@", [style_short stringFromDate : date]);
NSLog(@"en medium date : %@", [style_medium stringFromDate : date]);
NSLog(@"en long date : %@", [style_long stringFromDate : date]);
NSLog(@"en full date : %@", [style_full stringFromDate : date]);
}
}

-- ​执行结果​ : 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSDateFormatterTest.m 
localhost:oc_object octopus$ ./a.out
2015-10-07 18:54:08.207 a.out[825:507] cn short date : 15-10-7
2015-10-07 18:54:08.209 a.out[825:507] cn medium date : 2015年10月7日
2015-10-07 18:54:08.209 a.out[825:507] cn long date : 2015年10月7日
2015-10-07 18:54:08.210 a.out[825:507] cn full date : 2015年10月7日 星期三
2015-10-07 18:54:08.211 a.out[825:507] en short date : 10/7/15
2015-10-07 18:54:08.212 a.out[825:507] en medium date : Oct 7, 2015
2015-10-07 18:54:08.212 a.out[825:507] en long date : October 7, 2015
2015-10-07 18:54:08.213 a.out[825:507] en full date : Wednesday, October 7, 2015

3. 日历 (NSCalendar) 日期 (NSDateComponents) 组件

(1) 两个类简介

NSCalendar 与 NSDateComponents 简介​ : 

-- ​主要作用​ : 月, 日, 年 等数值转化为 NSDate, 从 NSDate 对象中提取 月, 日, 年 数值;

-- ​NSCalendar 作用 ​: NSDate 与 NSDateComponents 转化媒介;

-- ​NSDateComponents 作用​ : 专门封装 年月日时分秒 个字段信息, 包含了 year, month, day, hour, minute, second, week, weekday 等 字段的 getter 和 setter 方法;

(2) NSCalendar 常用方法

NSCalendar 常用方法​ : 

--​ NSDate -> 数据​ : "(NSDateComponents *) components : FromDate :", 从 NSDate 中提取 年月日时分秒 各个字段数据;

-- ​数据 -> NSDate​ : "dateFromComponents : (NSDateComponents *) comps", 使用 年月日时分秒 数据创建 NSDate;

(3) 获取 NSDate 中数据

NSDate 获取 日期数值数据​ : 

-- ​1.创建 NSCalendar 对象​ : 

-- 2.​获取 NSDateComponents 对象 ​: 调用 NSCalendar 的 "components : fromDate :" 方法获取 NSDateComponents 对象;

-- ​3.获取具体数值​ : 调用 NSDateComponents 对象的 getter 方法获取各字段具体数值;

(4) 获取 NSDate 中的数值数据

根据 日志数值数据 创建 NSDate ​: 

-- ​1.创建 NSCalendar 对象​ : 

-- ​2.创建 NSDateComponents 对象​ : 调用对象的 setter 方法, 将具体的数值设置到字段中去;

-- ​3.创建 NSDate 对象​ : 调用 NSCalendar 的 "dateFromComponents : (NSDateComponents *)" 初始化 NSDate 对象;

(5) NSCalendar 和 NSDateComponents 示例代码

示例代码​ : 

//
// main.m
// 01.Calendar
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 Calendar 对象
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier : NSGregorianCalendar];
//获取当前日期
NSDate * date = [NSDate date];
//指定 NSDateComponents 中含有的字段信息
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekCalendarUnit;
//获取 NSDateComponents 对象
NSDateComponents * components = [calendar components:unitFlags fromDate:date];
//将 NSDateComponents 对象中得字段打印出来
NSLog(@"%ld 年 %ld 月 %ld 日, %ld 时, %ld 分, %ld 秒, 星期 %ld", components.year, components.month, components.day, components.hour, components.minute, components.second, components.weekday);

//根据 NSDateComponents 创建 NSDate 对象
components.year = 3000;
NSDate * date1 = [calendar dateFromComponents:components];
NSLog(@"date1 : %@", date1);
}

}

-- ​执行结果​ : 

2015-10-08 09:56:28.695 01.Calendar[1255:303] 2015 年 10 月 8 日, 9 时, 56 分, 28 秒, 星期 9223372036854775807
2015-10-08 09:56:28.701 01.Calendar[1255:303] date1 : 3000-10-08 01:56:28 +0000
Program ended with exit code: 0

4. 定时器

(1) 定时器创建

创建定时器​ : 

-- ​两个创建方法​ : 调用 NSTimer 的 "scheduledTimeWithTimeInterval : repeats : " 方法, 或者 scheduledTimerWithTimeInterval : target : selector : userInfo : repeats : " 方法;

-- ​timeInterval 参数​ : 指定执行周期, 每隔多少时间执行一次;

-- ​target 与 selector 参数​ : 指定重复执行任务, 如果指定 target 或者 selector 参数, 则指定使用 target 的 selector 方法为执行的任务;

-- ​Invocation 参数​ : 传入一个 NSInvocation 对象, 该 NSInvocation 对象也是封装了一个 target 和 selector;

-- ​userInfo 参数​ : 传入额外的附加信息;

-- ​repeats 参数​ : 指定一个 BOOL 值, 指定是否需要循环执行任务;

(2) 定时器流程

定时器使用流程​ : 

-- ​创建定时器​ : 

[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:NSSelectorFromString(@"info:")
userInfo:nil
repeats: YES];

-- ​编写任务方法​ : 

-- ​销毁定时器​ :

[timer invalidate];


三. 对象拷贝

1. 拷贝方法 copy 与 mutableCopy

(1) 方法简介

拷贝方法简介​  : 

-- ​copy 方法​ : 复制对象的副本, 一般返回对象不可修改的副本; 假如被复制的对象是可修改的 NSMutableString, 复制后成为 NSString 不可修改;

-- ​mutableCopy 方法​ : 复制对象的可变副本, 返回对象的可变副本; 假如被复制对象不可修改 如 NSString, 使用该方法复制后为 NSMutableString 可以修改;

(2) 示例代码

示例代码​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSString * str = @"octopus";
NSMutableString * str_mutable = [NSMutableString stringWithString:@"octopus"];

//复制可变字符串
NSMutableString * str_mutable1 = [str mutableCopy];
NSMutableString * str_mutable2 = [str_mutable mutableCopy];

//验证可变字符串
[str_mutable1 appendString:@" mutable"];
[str_mutable2 appendString:@" mutable"];
NSLog(@"str_mutable1 : %@, str_mutable2 : %@", str_mutable1, str_mutable2);

//复制不可变字符串
NSString * str1 = [str copy];
NSMutableString * str2 = [str_mutable copy];
[str2 appendString:@" mutable"];
NSLog(@"str_mutable2 : %@", str_mutable2);
}
return 0;
}

-- ​执行结果​ : 后面的复制 不能被修改, 所以报错;

2015-10-08 20:14:57.690 03.Copy[760:303] str_mutable1 : octopus mutable, str_mutable2 : octopus mutable
2015-10-08 20:14:57.692 03.Copy[760:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8fda225c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e6a0e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8fda210c +[NSException raise:format:] + 204
3 CoreFoundation 0x00007fff8fd71dbe mutateError + 110
4 03.Copy 0x0000000100000dfc main + 348
5 libdyld.dylib 0x00007fff84bb85fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

2. 自定义 拷贝方法

(1) 自定义类拷贝方法

调用 copy 方法前提​ : 

-- ​1.该类实现了 NSCopying 协议​;

-- ​2.该类实现了 copyWithZone: 方法​;

调用 mutableCopy 方法前提​ : 

-- ​1.该类实现了 NSMutableCopying 协议​;

-- ​2.该类实现了 mutableCopyWithZone 方法​;

(2) 代码示例

自定义类赋值代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, strong) NSString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone]init];
cat.name = self.name;
cat.age = self.age;
return cat;
}


@end

-- ​main.m​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
cat2.name = [NSMutableString stringWithString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}

-- ​执行结果​ : 

2015-10-08 20:41:08.584 03.Copy[941:303] cat1.name : Cat One, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

3. 浅复制 深复制

(1) 浅拷贝示例

浅拷贝示例​ : 复制 cat2 对象是从 cat1 复制而来, 但是 cat1 中得 name 是一个 NSString * 引用对象, 这两个 cat1 cat2 都指向同一个 name 对象;

-- ​修改下之前的 main 函数​ : 

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
[(NSMutableString *)cat2.name replaceCharactersInRange:NSMakeRange(0, 7) withString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}



-- 

执行结果​ : 


2015-10-09 17:13:56.329 03.Copy[1744:303] cat1.name : Cat Two, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

(2) 深拷贝示例

深拷贝完整示例​ : 

-- ​OCCat.h​ : 与之前的相同;

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, strong) NSString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m ​: 只是在 copyWithZone 方法中, 将 name 赋值 改为 name copy 后赋值;

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone]init];
cat.name = [self.name mutableCopy];
cat.age = self.age;
return cat;
}


@end

-- ​main.m​ : 与之前相同;

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

OCCat * cat2 = [cat1 copy];
[(NSMutableString *)cat2.name replaceCharactersInRange:NSMakeRange(0, 7) withString:@"Cat Two"];
cat2.age = 20;

NSLog(@"cat1.name : %@, cat1.age : %d, cat2.name : %@, cat2.age : %d", cat1.name, cat1.age, cat2.name, cat2.age);
}
return 0;
}

-- ​执行结果​ : 

2015-10-09 17:27:22.302 03.Copy[1809:303] cat1.name : Cat One, cat1.age : 18, cat2.name : Cat Two, cat2.age : 20
Program ended with exit code: 0

4. setter 的 copy 参数

(1) copy 参数

copy 参数用处 ​: 

-- ​示例​ : 

@property (nonatomic, copy) NSMutableString * name;

-- ​作用​ : 为 name 属性 赋值时, 将赋值对象 copy 一份, 将副本赋值给 name 属性;

-- ​使用 copy 指令, 相当于将 setter 方法设置成如下状态​ : 

- (void) setName:(NSMutableString *)name1
{
this.name = [name1 copy];
}

(2) copy 参数示例

copy 代码错误使用示例 ​: copy 的属性, 赋值后 是不可变的, 如 NSMutableString 接收一个 NSString 赋值, 如果在对赋值后的属性执行 NSMutableString 的操作, 就会报错;

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSMutableString * name;
@property (assign, nonatomic) int age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

@end

-- ​main.h ​:

//
// main.m
// 03.Copy
//
// Created by octopus on 15-10-8.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {
OCCat * cat1 = [[OCCat alloc] init];
cat1.name = [NSMutableString stringWithString:@"Cat One"];
cat1.age = 18;

[cat1.name appendString:@" append"];
}
return 0;
}



-- 

执行结果​ : 


2015-10-09 23:17:01.469 03.Copy[2095:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8fda225c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e6a0e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8fda210c +[NSException raise:format:] + 204
3 CoreFoundation 0x00007fff8fd71dbe mutateError + 110
4 03.Copy 0x0000000100000d86 main + 246
5 libdyld.dylib 0x00007fff84bb85fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

四. NSArray NSMutableArray 数组集合


Objective-C 集合概述​ : 


-- ​NSArray​ : 有序, 可重复集合;

-- ​NSSet​ : 无序, 不可重复集合;

-- ​NSDictionary​ : 有映射关系的集合;

1. NSArray 基本功能用法

(1) NSArray 创建

NSArray 简介​ : 有序, 可重复集合;

-- ​特点​ : 每个元素都有对应的顺序索引, 允许重复元素, 通过索引来访问指定位置元素, 索引从 0 开始;

NSArray 对象创建​ : 

-- ​"array" 方法​ : 创建空得 NSArray 对象;

-- ​"arrayWithContentsOfFile : " 方法​ : 读取文件内容创建 NSArray 对象;

-- ​"initWithContentsOfFile : " 方法​ :  读取文件内容创建 NSArray 对象;

-- ​"arrayWithObject : " 方法​ : 创建只包含单个元素的 NSArray 对象;

-- ​"initWithObject : " 方法​ : 创建只包含单个元素的 NSArray 对象;

-- ​"arrayWithObjects : " 方法​ : 创建包含 N 个元素的 NSArray 对象, 最后一个 nil 元素, 表示 NSArray 集合结束;

NSArray * array = [NSArray arrayWithObjects:@"Smoke", @"Drink", @"Perm", nil];

-- ​"initWithObjects : " 方法​ : 创建包含 N 个元素的 NSArray 对象;

(2) NSArray 基本方法

NSArray 集合主要方法​ : 

-- ​查索引​ : 查询集合元素在 NSArray 中索引;

//获取元素在集合中得位置
NSLog(@"Index Of Drink at subArray is : %ld", [subArray indexOfObject:@"Drink"]);
NSLog(@"Index Of Drink at array is : %ld", [array indexOfObject:@"Drink" inRange:NSMakeRange(1, 2)]);

-- ​查元素​ : 根据索引值 取出 NSArray 集合中得元素;

// 获取 第 0 1 最后一个元素 并打印
NSLog(@"First : %@", [array objectAtIndex:0]);
NSLog(@"Second : %@", [array objectAtIndex:1]);
NSLog(@"Last : %@", [array lastObject]);

-- ​整体调用​ : 对集合元素整体调用的方法;

-- ​排序 ​: 对 NSArray 集合进行排序;

-- ​截取元素​ : 取出 NSArray 部分元素组成新集合;

//截取 1 2 个元素组成新 NSArray 集合对象
NSArray * subArray = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];



-- 

追加元单个素​ : "arrayByAddingObject : " 追加单个元素;


array = [array arrayByAddingObject:@"Run"];

-- ​追加数组​ : "arrayWithObjects : " 追加一个数组;

array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"Jump", @"Fuck", nil]];

(3) NSArray 基本方法 示例代码

示例代码​ : 

-- ​OCCat.h ​: 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 NSArray 对象
NSArray * array = [NSArray arrayWithObjects:@"Smoke", @"Drink", @"Perm", nil];

// 获取 第 0 1 最后一个元素 并打印
NSLog(@"First : %@", [array objectAtIndex:0]);
NSLog(@"Second : %@", [array objectAtIndex:1]);
NSLog(@"Third: %@", array[2]);
NSLog(@"Last : %@", [array lastObject]);

// 打印整个 array
NSLog(@"array : \n%@", array);

//截取 1 2 个元素组成新 NSArray 集合对象, NSIndexSet 集合用于保存索引值
NSArray * subArray = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];

//获取元素在集合中得位置
NSLog(@"Index Of Drink at subArray is : %ld", [subArray indexOfObject:@"Drink"]);
NSLog(@"Index Of Drink at array is : %ld", [array indexOfObject:@"Drink" inRange:NSMakeRange(1, 2)]);

//添加单个元素
array = [array arrayByAddingObject:@"Run"];
//追加一个 NSArray 集合, nil 结尾表示 NSArray 结束
array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"Jump", @"Fuck", nil]];
//遍历 array
for (int i = 0; i < array.count; i ++) {
NSLog(@"array %d : %@", i, [array objectAtIndex:i]);
}

//将字符串写出到文件中
[array writeToFile:@"array.txt" atomically:YES];

//创建 OCCat 的 array
NSArray * array2 = [NSArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age : 20],
nil];
//打印 array, 验证 重写的 description 方法
NSLog(@"array2 is : \n%@", array2);
OCCat* cat = [[OCCat alloc] initWithName : @"Tom" age : 18];
//获取 元素 在 array 中的位置, 验证 isEqual 方法
NSUInteger index = [array2 indexOfObject:cat];
NSLog(@"index Of Tom is : %ld", index);


}
return 0;
}

-- ​执行结果​ : 

2015-10-14 17:16:12.748 04.NSArray[7155:303] First : Smoke
2015-10-14 17:16:12.750 04.NSArray[7155:303] Second : Drink
2015-10-14 17:16:12.751 04.NSArray[7155:303] Third: Perm
2015-10-14 17:16:12.751 04.NSArray[7155:303] Last : Perm
2015-10-14 17:16:12.751 04.NSArray[7155:303] array :
(
Smoke,
Drink,
Perm
)
2015-10-14 17:16:12.752 04.NSArray[7155:303] Index Of Drink at subArray is : 0
2015-10-14 17:16:12.752 04.NSArray[7155:303] Index Of Drink at array is : 1
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 0 : Smoke
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 1 : Drink
2015-10-14 17:16:12.753 04.NSArray[7155:303] array 2 : Perm
2015-10-14 17:16:12.754 04.NSArray[7155:303] array 3 : Run
2015-10-14 17:16:12.754 04.NSArray[7155:303] array 4 : Jump
2015-10-14 17:16:12.755 04.NSArray[7155:303] array 5 : Fuck
2015-10-14 17:16:12.769 04.NSArray[7155:303] array2 is :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>"
)
2015-10-14 17:16:12.769 04.NSArray[7155:303] index Of Tom is : 0
Program ended with exit code: 0

2. NSArray 集合整体调用

(1) NSArray 整体元素调用简介

调用所有元素方法​ : 

-- ​"makeObjectPerformSelector : " 方法​ : 按顺序 依次 调用 NSArray 中集合的每个元素, 需要传入 SEL 参数, 该参数指定需要调用的方法;

-- ​"makeObjectPerformSelector : withObject : " 方法​ : 参数一 SEL 代表的方法, 参数二 方法的参数, 参数三 控制是否终止迭代;

-- ​"enumerateObjectsUsingBlock : " 方法​ : 遍历集合中元素, 使用 集合中的元素 执行指定代码块;

-- ​"enumerateObjectsWithOptions : usingBlock : " 方法​ : 遍历元素, 依次使用元素执行代码块, 可以额外传入一个参数控制遍历选项;

-- ​"enumerateObjectsAtIndexs : options : usingBlock : " 方法​ : 遍历指定范围元素, 依次使用元素执行代码块, 传入最后的参数用于控制遍历; 

(2) NSArray 整体元素调用代码示例

代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建 OCCat 的 array
NSArray * array = [NSArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age : 20],
nil];

NSLog(@"array is : \n%@", array);

[array makeObjectsPerformSelector:@selector(purr:) withObject:@" FUCK YOU "];


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 10:50:49.902 04.NSArray[8086:303] array is : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>"
)
2015-10-15 10:50:49.905 04.NSArray[8086:303] cat name : Tom, age 18 is purr
2015-10-15 10:50:49.905 04.NSArray[8086:303] cat name : Jerry, age 20 is purr
Program ended with exit code: 0

3. NSArray 排序

(1) NSArray 排序简介

NSArray 排序​ : 

-- ​"sortArrayUsingFunction : context : " 方法​ : 使用排序函数对集合进行排序, 函数会返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时会返回一个 排序号的 NSArray 集合;

-- ​"sortArrayUsingSelector : " 方法​ : 使用集合元素自身的方法对集合进行排序, 该方法返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时还会返回一个 排序号的 NSArray 集合;

-- ​"sortArrayUsingComparator : " 方法​ : 使用代码块对集合进行排序, 代码块 返回 NSOrderedDescending, NSOrderedAscending, NSOrderedSame 枚举值, 同时返回排序号的 NSArray 集合;

(2) NSArray 排序代码示例

NSArray 排序示例代码​ : 

-- ​main.c​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

NSInteger intSort(id num1, id num2, void * context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];

if(v1 < v2)
{
return NSOrderedAscending;
}

if(v1 > v2)
{
return NSOrderedDescending;
}

return NSOrderedSame;
}

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//使用 compare 方法进行排序
array = [array sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"array sort : \n%@\n", array);

//创建一个 NSNumber 元素的 NSarray 集合
NSArray * array_num = [NSArray arrayWithObjects:
[NSNumber numberWithInt:18],
[NSNumber numberWithInt:16],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:-1],
nil];
NSLog(@"array_num : \n%@\n", array_num);

//使用 intSort 方法进行排序
array_num = [array_num sortedArrayUsingFunction:intSort context:nil];
NSLog(@"array_num sort : \n%@\n", array_num);

//使用代码块进行排序
array_num = [array_num sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
if([obj2 intValue] < [obj1 intValue])
{
return NSOrderedAscending;
}

if([obj2 intValue] > [obj1 intValue])
{
return NSOrderedDescending;
}

return NSOrderedSame;
}];
NSLog(@"array_num : \n%@\n", array_num);


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 11:52:51.335 04.NSArray[8465:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 11:52:51.336 04.NSArray[8465:303] array sort :
(
Fuck,
Jerry,
Tom
)
2015-10-15 11:52:51.337 04.NSArray[8465:303] array_num :
(
18,
16,
20,
"-1"
)
2015-10-15 11:52:51.337 04.NSArray[8465:303] array_num sort :
(
"-1",
16,
18,
20
)
2015-10-15 11:52:51.338 04.NSArray[8465:303] array_num :
(
20,
18,
16,
"-1"
)
Program ended with exit code: 0

4. NSArray 枚举器遍历

(1) NSArray 获取枚举器

NSArray 枚举器 NSEnumerator 简介​ : 

-- ​"objectEnumerator : " 方法​ : 返回 NSArray 集合顺序枚举器;

-- ​"reverseObjectEnumerator : "  方法​ : 返回 NSArray 集合的逆序枚举器;

(2) NSEnumerator 枚举器

NSEnumerator 方法简介​ : 

-- ​"allObjects : " 方法​ : 获取集合中的所有元素;

-- ​"nextObjects : " 方法​ : 获取集合中的下一个元素;

(3) NSEnumerator 枚举器示例代码

NSEnumerator 示例代码​ : 

-- ​main.m 代码​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//顺序枚举
NSEnumerator * enumerator = [array objectEnumerator];
id object;
while (object = [enumerator nextObject]) {
NSLog(@"%@", object);
}

NSLog(@"\n");

//逆序枚举
NSEnumerator * reverseEnumerator = [array reverseObjectEnumerator];
while (object = [reverseEnumerator nextObject]) {
NSLog(@"%@", object);
}


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:09:59.170 04.NSArray[8590:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 12:09:59.176 04.NSArray[8590:303] Tom
2015-10-15 12:09:59.177 04.NSArray[8590:303] Jerry
2015-10-15 12:09:59.177 04.NSArray[8590:303] Fuck
2015-10-15 12:09:59.178 04.NSArray[8590:303]
2015-10-15 12:09:59.178 04.NSArray[8590:303] Fuck
2015-10-15 12:09:59.178 04.NSArray[8590:303] Jerry
2015-10-15 12:09:59.179 04.NSArray[8590:303] Tom
Program ended with exit code: 0

5. NSArray 快速枚举

(1) NSArray 快速枚举

快速枚举简介​ : 快速枚举无需获取集合长度, 也不用根据索引访问集合元素;

-- ​语法​ : 

for (id object in array)
{
//对 object 进行操作
}

(2) NSArray 快速枚举示例

NSArray 快速枚举示例​ : 

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

//创建一个 NSarray 集合, 其中放置 NSString 元素
NSArray * array = [NSArray arrayWithObjects:@"Tom", @"Jerry", @"Fuck", nil];
NSLog(@"array : \n%@\n", array);

//快速枚举
for(id object in array)
{
NSLog(@"%@", object);
}


}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:17:36.096 04.NSArray[8642:303] array : 
(
Tom,
Jerry,
Fuck
)
2015-10-15 12:17:36.098 04.NSArray[8642:303] Tom
2015-10-15 12:17:36.098 04.NSArray[8642:303] Jerry
2015-10-15 12:17:36.099 04.NSArray[8642:303] Fuck
Program ended with exit code: 0

6. NSMutableArray 可变数组

(1) NSMutableArray 简介

NSMutableArray 简介​ : 

-- ​NSMutableArray 与 NSArray 对比​ : NSArray 是不可变数组, 一旦创建不能增删替换元素, NSMutableArray 可以随时增加 删除 替换 元素;

-- ​"addXX" 方法​ : 添加集合元素的方法;

-- ​"removeXX" 方法​ : 删除集合元素的方法;

-- ​"replaceXX" 方法​ : 替换集合元素的方法;

-- ​"sortXX" 方法​ : 对集合本身排序的方法; 

(2) NSMutableArray 代码示例

NSMutableArray 代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{


@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age: 20],
[[OCCat alloc] initWithName : @"Jay" age : 180],
nil];
NSLog(@"array 原始数组 : \n%@\n", array);

//添加单个元素
[array addObject:[[OCCat alloc] initWithName:@"octopus" age:26]];
NSLog(@"array 追加单个元素 : \n%@\n", array);

//添加数组
[array addObjectsFromArray:[NSArray arrayWithObjects:
[[OCCat alloc] initWithName:@"HanShuliang" age:26],
[[OCCat alloc] initWithName:@"Bill" age:60],
nil]];
NSLog(@"array 追加集合 : \n%@\n", array);

//插入单个元素
[array insertObject : [[OCCat alloc] initWithName:@"Green" age:26] atIndex:0];
NSLog(@"array 插入单个元素 : \n%@\n", array);

//插入集合
[array insertObjects: [NSArray arrayWithObjects:
[[OCCat alloc] initWithName:@"LiKeqiang" age:26],
[[OCCat alloc] initWithName:@"Son" age:60],
nil]
atIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)]];
NSLog(@"array 插入集合 : \n%@\n", array);

//删除最后一个元素
[array removeLastObject];
NSLog(@"array 删除最后一个元素 : \n%@\n", array);

//删除第3个元素
[array removeObjectAtIndex:3];
NSLog(@"array 删除第三个元素 : \n%@\n", array);

//删除第3,4个元素
[array removeObjectsInRange:NSMakeRange(3, 2)];
NSLog(@"array 删除第3,4个元素 : \n%@\n", array);

//替换第0个元素
[array replaceObjectAtIndex:0 withObject:[[OCCat alloc] initWithName:@"HanShuliang" age:28]];
NSLog(@"array 替换第0个元素 : \n%@\n", array);




}
return 0;
}

-- ​执行结果​ : 

2015-10-15 12:51:43.749 04.NSArray[9033:303] array 原始数组 : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>"
)
2015-10-15 12:51:43.752 04.NSArray[9033:303] array 追加单个元素 :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>"
)
2015-10-15 12:51:43.752 04.NSArray[9033:303] array 追加集合 :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.753 04.NSArray[9033:303] array 插入单个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.753 04.NSArray[9033:303] array 插入集合 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Son, age = 60]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>",
"<OCCat [name = Bill, age = 60]>"
)
2015-10-15 12:51:43.755 04.NSArray[9033:303] array 删除最后一个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Son, age = 60]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.756 04.NSArray[9033:303] array 删除第三个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.757 04.NSArray[9033:303] array 删除第3,4个元素 :
(
"<OCCat [name = Green, age = 26]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
2015-10-15 12:51:43.757 04.NSArray[9033:303] array 替换第0个元素 :
(
"<OCCat [name = HanShuliang, age = 28]>",
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = LiKeqiang, age = 26]>",
"<OCCat [name = octopus, age = 26]>",
"<OCCat [name = HanShuliang, age = 26]>"
)
Program ended with exit code: 0

7. NSArray 的 KVO KVC 用法

(1) NSArray KVC 简介

NSArray KVC 简介​ : NSArray 可以对元素进行整体 KVC 编码;

-- ​"setValue : forKey : " 方法​ : 将所有元素的制定 key 变量设置为 某个值;

-- ​"valueForKey : " 方法​ : 返回 所有元素指定变量值组成的 NSArray 集合;

(2) NSArray KVO 简介

NSArray KVO 简介​ : NSArray 中可以对所有元素进行 KVO 编程;

-- ​"addObserver : forKeyPath : options : context : " 方法 ​: 为集合中所有元素添加 KVO 监听器;

-- ​"removeObserver : forKeyPath : " 方法​ : 为集合中所有元素删除 KVO 监听器;

-- ​"addObserver : toObjectAtIndexes : forKeyPath : options : context : " 方法​ : 为集合中指定元素添加 KVO 监听;

-- ​"removeObserver : fromObjectsAtIndexes : forKeyPath : " 方法​ : 为集合中指定元素删除 KVO 监听;

(3) NSArray KVC KVO 示例代码

NSArray KVC KVO 示例代码​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithName : (NSString *) _name age : (int) _age;
- (void) purr : (NSString *) content;
@end

-- ​OCCat.m ​: 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;
- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (void) purr:(NSString *)content
{
NSLog(@"cat name : %@, age %d is purr", self.name, self.age);
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

--​ main.m​ : 

//
// main.m
// 04.NSArray
//
// Created by octopus on 15-10-13.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{


@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[[OCCat alloc] initWithName : @"Tom" age : 18],
[[OCCat alloc] initWithName : @"Jerry" age: 20],
[[OCCat alloc] initWithName : @"Jay" age : 180],
nil];
NSLog(@"array 原始数组 : \n%@\n", array);

NSArray * str_array = [array valueForKeyPath:@"name"];
NSLog(@"str_array : \n%@\n", str_array);

[array setValue:@"octopus" forKeyPath:@"name"];
NSLog(@"array 设置 KVC 后的数组 : \n%@\n", array);




}
return 0;
}

-- ​执行结果​ : 

2015-10-15 13:07:04.116 04.NSArray[9135:303] array 原始数组 : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Jay, age = 180]>"
)
2015-10-15 13:07:04.118 04.NSArray[9135:303] str_array :
(
Tom,
Jerry,
Jay
)
2015-10-15 13:07:04.118 04.NSArray[9135:303] array 设置 KVC 后的数组 :
(
"<OCCat [name = octopus, age = 18]>",
"<OCCat [name = octopus, age = 20]>",
"<OCCat [name = octopus, age = 180]>"
)
Program ended with exit code: 0


五. NSSet 与 NSmutableSet 集合


1. NSSet 功能与用法

(1) NSSet 简介

NSSet 功能简介​ : 

-- ​基本属性​ : 无序, 不可重复; 如果将两个相同的元素放在同一个 NSSet 中, 只会保留一个;

-- ​性能分析​ : NSSet 使用 hash 方法存储集合中的元素, 存取 和 查找性能很好;

(2) NSSet 与 NSArray 的相同之处

NSSet 与 NSArray 相同之处​ : 

-- ​获取元素数量​ : 调用 count 方法获取集合元素数量;

-- ​快速枚举​ : 都可以通过 for (id object in collection) 快速枚举来遍历元素;

-- ​枚举器​ : 都可以通过 objectEnumerator 方法获取 NSEnumerator 枚举器对集合元素进行遍历;

-- ​方法遍历​ : 都可以通过 "makeObjectPerformSelector : " 和 "makeObjectPerformSelector : withObject : " 方法对集合元素整体调用某个方法;

-- ​代码块遍历​ : 都可以通过 "enumerateObjectUsingBlock : " 和 "enumerateObjectWithOptions : usingBlock : " 使用代码块遍历执行集合元素;

-- ​KVC 编程​ : 都可以通过 "valueForKey : " 和 "setValue : forKey : " 进行所有元素的 KVC 编程;

-- ​KVO 编程​ : 都可以通过 "addObserver : forKeyPath : options : context : " 等方法进行 KVO 编程; 

(3) NSSet 常用方法

NSSet 常用方法​ : 

-- ​"setByAddingObject : " 方法​ : 向集合中添加一个新元素, 返回新集合;

-- ​"setByAddingObjectFromSet : " 方法​ : 向 NSSet 集合中添加一个 NSSet 集合, 返回新集合;

-- ​"setByAddingObjectFromArray : " 方法​ : 向 NSSet 集合中添加一个 NSArray 集合, 返回新集合;

-- ​"allObjects : " 方法​ : 将 NSSet 集合中所有元素组成 NSArray , 并返回 NSArray 集合;

-- ​"anyObject : " 方法​ : 返回 NSSet 集合中的某个元素;

-- ​"containsObject : " 方法​ : 判断是否包含 某元素;

-- ​"member : "方法​ : 判断是否包含指定元素, 如果包含返回该元素, 否则返回 nil;

-- ​"objectPassingTest : " 方法​ : 使用代码块过滤集合元素, 通过验证的元素组成新的 NSSet 集合并返回该集合;

-- ​"objectWithOptions : passingTest : " 方法​ : 在 "objectPassingTest : " 基础上额外传入一个 NSEnumerationOptions 参数遍历元素; 

-- ​"isSubsetOfSet : " 方法​ : 判断当前 NSSet 集合是否是另外一个集合的子集合;

-- ​"intersectsSet : " 方法​ : 计算两个集合是否有交集;

-- ​"isEqualToSet : " 方法​ : 判断两个集合元素是否相等;

(4) NSSet 代码示例

NSSet 代码示例​ : 

-- ​代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSSet * set = [NSSet setWithObjects:@"Tom", @"Jerry", @"Hank", nil];

//输出集合大小
NSLog(@"set 集合大小 : %ld", [set count]);

NSSet * set1 = [NSSet setWithObjects:@"Angle", @"Devil", nil];
//添加单个元素
set1 = [set1 setByAddingObject:@"Han"];
//添加整个集合
set1 = [set1 setByAddingObjectsFromSet:set];

//输出合并后的 NSSet
NSLog(@"set 与 set1 合并后的 NSSet : \n%@", set1);

//判断交集
BOOL b1 = [set intersectsSet:set1];
NSLog(@"set1 与 set 是否有交集 : %d", b1);

//判断 set 是否是 set1 的子集
BOOL b2 = [set isSubsetOfSet:set1];
NSLog(@"set 是否是 set1 的子集 : %d", b2);

//判断 set 是否包含 Tom 字符串
BOOL b3 = [set containsObject:@"Tom"];
NSLog(@"set 是否包含 Tom : %d", b3);

//过滤
NSSet * set2 = [set1 objectsPassingTest:^BOOL(id obj, BOOL *stop) {
return (BOOL)([obj length] > 4);
}];
NSLog(@"过滤后的 set2 : \n%@", set2);



}
return 0;
}

-- ​执行结果​ : 

2015-10-18 10:49:22.118 05.NSSet[11008:303] set 集合大小 : 3
2015-10-18 10:49:22.120 05.NSSet[11008:303] set 与 set1 合并后的 NSSet :
{(
Hank,
Jerry,
Han,
Devil,
Angle,
Tom
)}
2015-10-18 10:49:22.120 05.NSSet[11008:303] set1 与 set 是否有交集 : 1
2015-10-18 10:49:22.121 05.NSSet[11008:303] set 是否是 set1 的子集 : 1
2015-10-18 10:49:22.121 05.NSSet[11008:303] set 是否包含 Tom : 1
2015-10-18 10:49:22.122 05.NSSet[11008:303] 过滤后的 set2 :
{(
Jerry,
Devil,
Angle
)}
Program ended with exit code: 0

2. NSSet 判重原理

(1) NSSet 重复判定原理

NSSet 添加元素判断​ : 

-- ​位置判断​ : 向 NSSet 中添加元素时, NSSet 会调用对象的 hash 方法 获取对象的 哈希值, 根据 HashCode 判断元素在 NSSet 哈希表中的存储位置;

-- ​重复判断​ : 两个元素 HashCode 相同, 通过 isEqual : 方法判断, 如果返回 NO 则将两个元素放在同一个位置, 如果返回 YES 添加失败;

NSSet 判断元素相同标准​ : 

-- ​值相等​ : 调用 isEqual : 方法返回 YES;

-- ​hashCode 相等​ : 元素的 hash 方法返回值相同;

(2) hash 方法规则

注意 ​: 

-- ​重写对象​ : 如果重写了对象的 isEqual 方法, 其 hash 方法也应该被重写, 尽量保持 isEqual 方法返回 YES 时, hash 方法也返回 YES;

-- ​关于同一位置存储​ : hashCode 相同, isEqual 不同的时候, 同一个位置存储多个元素, 需要用链表连接这些元素, 这会降低 NSSet 访问性能;

hash 方法规则​ : 

-- ​同一对象返回的值相同​;

-- ​isEqual 方法返回值相同时, hash 方法返回的值也应该相同​;

-- ​isEqual 标准的实例变量应该用 hashCode 计算​;

(3) 代码实例

代码实例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

@end

-- ​main.m​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSSet * set = [NSSet setWithObjects:
[[OCCat alloc] initWithName:@"Tom" age:18],
[[OCCat alloc] initWithName:@"Jerry" age:20],
[[OCCat alloc] initWithName:@"Tom" age:18],
nil];
NSLog(@"set 集合个数 : %ld \n内容 : \n%@", [set count], set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 12:17:44.740 05.NSSet[11464:303] set 集合个数 : 2 
内容 :
{(
<OCCat [name = Tom, age = 18]>,
<OCCat [name = Jerry, age = 20]>
)}
Program ended with exit code: 0

3. NSMutableSet 功能与用法

(1) NSMutableSet 简介

NSMutableSet 简介​ : NSMutableSet 可以动态添加, 删除, 修改 集合元素, 可计算集合的 交集 并集 差集;

-- ​"addObject : " 方法​ : 向集合中添加单个元素;

-- ​"removeObject : " 方法​ : 从集合中删除单个元素;

-- ​"removeAllObjects" 方法 ​: 删除集合中所有元素;

-- ​"addObjectsFromArray : " 方法​ : 向 NSSet 集合中添加 NSArray 集合中的所有元素;

-- ​"unionSet : " 方法​ : 计算两个 NSSet 并集;

-- ​"minusSet : " 方法​ : 计算两个 NSSet 集合的差集;

-- ​"setSet : " 方法​ : 用一个集合的元素 替换 已有集合的所有的元素;

(2) NSMutableSet 代码示例

NSMutableSet 示例代码​ : 

-- ​示例代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableSet * set = [NSMutableSet setWithCapacity:5];
//添加一个
[set addObject:@"Tom"];
//添加3个 元素 从 NSArray
[set addObjectsFromArray:[NSArray arrayWithObjects:@"Jerry", @"Cat", @"Mouse", nil]];
//去掉一个
[set removeObject:@"Mouse"];
NSLog(@"添加一个 添加 3个 去掉一个后的 set : \n%@", set);

NSSet * set2 = [NSSet setWithObjects:@"Tom", @"Hank", nil];
[set unionSet:set2];
NSLog(@"合集是 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 17:57:14.948 05.NSSet[11656:303] 添加一个 添加 3个 去掉一个后的 set : 
{(
Jerry,
Cat,
Tom
)}
2015-10-18 17:57:14.950 05.NSSet[11656:303] 合集是 :
{(
Jerry,
Cat,
Hank,
Tom
)}
2015-10-18 17:57:14.950 05.NSSet[11656:303] 差集是 :
{(
Jerry,
Cat
)}
Program ended with exit code: 0

4. NSCountedSet 功能与用法

(1) NSCountedSet 简介

NSCountedSet 简介​ : 

-- ​增加元素​ : 该类是 NSMutableSet 的子类, 为每个元素维护了一个 计数 状态, 向该 NSCountedSet 中添加一个元素时, 如果添加成功, 则该元素的添加计数 标注为 1, 如果添加失败, 会再该元素的添加计数 +1; 

-- ​删除元素​ : 从 NSCountedSet 集合中删除元素时, 计数会 -1, 某元素的添加计数减到 0 会删除这个元素;

-- "countForObject : " 方法 : 获取指定元素的添加次数;

(2) NSCountedSet 示例代码

示例代码​ : 

-- ​代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSCountedSet * set = [NSCountedSet setWithObjects:@"Tom", @"Jerry", @"Hank", nil];
[set addObject:@"Tom"];
[set addObject:@"Tom"];

NSLog(@"set : \n%@", set);

[set removeObject:@"Tom"];
NSLog(@"set 删除一次后的效果 : \n%@", set);

[set removeObject:@"Tom"];
[set removeObject:@"Tom"];

NSLog(@"set 删除三次后的效果 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 18:10:56.253 05.NSSet[11746:303] set : 
<NSCountedSet: 0x100200330> (Tom [3], Jerry [1], Hank [1])
2015-10-18 18:10:56.255 05.NSSet[11746:303] set 删除一次后的效果 :
<NSCountedSet: 0x100200330> (Tom [2], Jerry [1], Hank [1])
2015-10-18 18:10:56.255 05.NSSet[11746:303] set 删除三次后的效果 :
<NSCountedSet: 0x100200330> (Jerry [1], Hank [1])
Program ended with exit code: 0

5. NSOrderedSet 与 NSMutableOrderedSet 有序集合

(1) 有序集合简介

NSOrderedSet 简介​ : 

-- ​特点​ : 不允许重复, 可以保持元素添加顺序, 每个元素都有索引, 可以根据索引操作元素;

(2) 有序集合代码示例

有序集合代码示例​ : 

-- ​main.m 代码​ : 

//
// main.m
// 05.NSSet
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSOrderedSet * set = [NSOrderedSet orderedSetWithObjects:@"Tom", @"Jerry", @"Hank", nil];

NSLog(@"第1个元素 : %@", [set firstObject]);
NSLog(@"第2个元素 : %@", [set objectAtIndex : 1]);
NSLog(@"最后1个元素 : %@", [set lastObject]);
NSLog(@"Tom 的索引 : %ld", [set indexOfObject : @"Tom"]);

NSIndexSet * index_set = [set indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return (BOOL) ([obj length] > 3);
}];
NSLog(@"%@", index_set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-18 18:31:30.562 05.NSSet[11925:303] 第1个元素 : Tom
2015-10-18 18:31:30.564 05.NSSet[11925:303] 第2个元素 : Jerry
2015-10-18 18:31:30.565 05.NSSet[11925:303] 最后1个元素 : Hank
2015-10-18 18:31:30.565 05.NSSet[11925:303] Tom 的索引 : 0
2015-10-18 18:31:30.566 05.NSSet[11925:303] <NSIndexSet: 0x100103760>[number of indexes: 2 (in 1 ranges), indexes: (1-2)]
Program ended with exit code: 0

六. NSDictionary 与 NSMutableDictionary 字典集合


1. NSDictionary 功能与用法

(1) NSDictionary 简介

NSDictionary 简介​ : 

-- ​作用 ​: NSDictionary 集合用于保存具有映射关系的数据, 其中保存两组数据, 一组是 key, 一组是 value, key 不允许重复;

-- ​key 与 value 对应关系​ : key 与 value 是一一对应的, 每个 key 都能找到对应的 value;

(2) NSDictionary 方法简介

NSDictionary 创建方法简介​ : 

-- ​"dictionary : " 方法​ : 创建不包含任何 key value 的 NSDictionary 集合;

-- ​"dictionaryWithContentsOfFile : / initWithContentsOfFile : " 方法​ : 读取文件, 使用文件内容生成 NSDictionary 集合, 一般这种文件是从 NSDictionary 集合输出的, 需要有指定的格式;

-- ​"dictionaryWithDictionary : / initWithDictionary : " 方法​ : 使用现有的 NSDictionary 生成新的 NSDictionary;

-- ​"dictionaryWithObject : forKey : " 方法​ : 使用单个 key-value 创建 NSDictionary 集合;

-- ​"dictionaryWithObjects : forKeys : / initWithObjects : forKeys : " 方法​ : 使用两个 NSArray 分别指定 key 和 value 集合;

-- ​"dictionaryWithObjectsAndKeys : / initWithObjectAndKeys : " 方法​ : 调用该方法, 需要按照 key-value 格式传入多个 键值对集合;

(3) NSDictionary 常用方法

NSDictionary 常用方法​ : 

--​ "count : " 方法​ : 返回 NSDictionary 含有的 key-value 的数量;

-- ​"allKeys : " 方法​ : 返回 NSDictionary 集合含有的 key 集合;

-- ​"allKeysForObject : " 方法​ : 返回指定 Value 的全部 key 的集合;

-- ​"allValues : " 方法​ : 该方法返回 NSDictionary 包含的全部 value 集合;

-- ​"objectForKeyedSubscript : " 方法​ : 允许 NSDictionary 通过下标方法获取指定 key 的 value;

-- ​"valueForKey : " 方法​ : 获取 NSDictionary 指定 key 的 value 值;

-- ​"keyEnumerator : " 方法​ : 返回 key 集合的 NSEnumerator 对象;

-- ​"objectEnumerator : " 方法​ : 返回 value 集合的 NSEnumerator 对象;

-- ​"enumerateKeysAndObjectsUsingBlock : " 方法​ : 使用指定的代码块迭代集合中的键值对;

-- ​"enumerateKeysAndObjectsWithOptions : usingBlock : " 方法 ​: 使用指定代码块迭代集合中的键值对, 额外传入一个 NSEnumerationOptions 参数;

-- ​"writeToFile : atomically : " 方法​ : 将 NSDictionary 对象数据写入文件中;

(4) NSDictionary 示例代码

NSDictionary 示例代码​ : 

-- ​NSDictionary+toString.h​ : 

//
// NSDictionary+toString.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSDictionary (toString)
- (void) toString;
@end

-- ​NSDictionary+toString.m​ : 

//
// NSDictionary+toString.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "NSDictionary+toString.h"

@implementation NSDictionary (toString)
- (void) toString
{
NSMutableString * string = [NSMutableString stringWithString:@"{"];

for(id key in self)
{
[string appendString:[key description]];
[string appendString:@" = "];
[string appendString:[self[key] description]];
[string appendString:@" , "];
}

[string appendString:@"}"];
NSLog(@"%@", string);
}
@end

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}
@end

-- ​main.m​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

NSLog(@"dictionary 键值对个数 : %ld", [dictionary count]);

NSLog(@"打印所有 key : \n%@", [dictionary allKeys]);

NSLog(@"打印所有 value : \n%@", [dictionary allValues]);

//枚举器遍历
NSEnumerator * enumerator = [dictionary objectEnumerator];
NSObject * value;
while(value = [enumerator nextObject])
{
NSLog(@"%@", value);
}

//使用代码块遍历 NSDictionary 集合
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

NSLog(@"key : %@ , value : %@", key, obj);
}];



}
return 0;
}

-- 执行结果 : 

2015-10-18 21:49:15.902 06.NSDictionary[12562:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-18 21:49:15.904 06.NSDictionary[12562:303] dictionary 键值对个数 : 3
2015-10-18 21:49:15.904 06.NSDictionary[12562:303] 打印所有 key :
(
Tom,
Jerry,
Hank
)
2015-10-18 21:49:15.905 06.NSDictionary[12562:303] 打印所有 value :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = Jerry, age = 20]>",
"<OCCat [name = Hank, age = 26]>"
)
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Tom, age = 18]>
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Jerry, age = 20]>
2015-10-18 21:49:15.910 06.NSDictionary[12562:303] <OCCat [name = Hank, age = 26]>
2015-10-18 21:49:15.911 06.NSDictionary[12562:303] key : Tom , value : <OCCat [name = Tom, age = 18]>
2015-10-18 21:49:15.911 06.NSDictionary[12562:303] key : Jerry , value : <OCCat [name = Jerry, age = 20]>
2015-10-18 21:49:15.912 06.NSDictionary[12562:303] key : Hank , value : <OCCat [name = Hank, age = 26]>
Program ended with exit code: 0

2. NSDictionary key 排序

(1) NSDictionary Key 排序简介

NSDictionary 排序方法​ : 

-- ​"keysSortedByValueUsingSelector : " 方法​ : 根据 ​value 指定方法​ 遍历 key-value 键值对, 对 key 排序, ​value 的指定方法必返回 NSOrderedSame, NSOrderedAscending 或 NSOrderedDescending 返回值​; 

-- ​"keysSortedByValueUsingComparator" 方法​ : 根据 ​指定代码块​ 遍历 键值对, 对 key 进行排序, ​代码块方法 需要返回 NSOrderedAscending, NSOrderedDescending 或 NSOrderedSame 返回值​;

-- ​"keysSortedByValueWithOptions : usingComparator : " 方法​ : 与前一个类似, 额外增加了一个 NSEnumerationOptions 参数;

(2) NSDictionary key排序示例代码

NSDictionary Key 排序示例代码​ : 

-- ​OCCat.h​ : 定义 compare : 比较方法;

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
- (NSComparisonResult) compare : (id) other;
@end

-- ​OCCat.m​ : 实现 compare : 比较方法;

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ :  

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

//使用 keysSortedByValueUsingSelector 方法排序
NSArray * array = [dictionary keysSortedByValueUsingSelector:@selector(compare:)];
NSLog(@"array : \n%@", array);

//使用代码块排序
NSArray * array2 = [dictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) {
OCCat * cat1 = (OCCat *)obj1;
OCCat * cat2 = (OCCat *)obj2;
if(cat1.age == cat2.age)
{
return NSOrderedSame;
}

if(cat1.age > cat2.age)
{
return NSOrderedDescending;
}

return NSOrderedAscending;
}];
NSLog(@"array2 : \n%@", array2);

}
return 0;
}

-- ​执行结果​ : 

2015-10-19 12:57:17.276 06.NSDictionary[13537:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-19 12:57:17.279 06.NSDictionary[13537:303] array2 :
(
Tom,
Jerry,
Hank
)
2015-10-19 12:57:17.279 06.NSDictionary[13537:303] array :
(
Tom,
Jerry,
Hank
)
Program ended with exit code: 0

3. NSDictionary key 过滤

(1) NSDictionary Key 过滤方法简介

NSDictionary key 过滤方法简介​ : 

-- ​"keysOfEntriesPassingTest : " 方法 ​: 使用代码块 遍历 键值对, 代码块返回一个 BOOL 值, 参数一 是 key, 参数二 是 value, 第三个是循环标志位;

-- ​"keysOfEntriesWithOptions : passingTest : " 方法​ : 与前一个方法功能基本相同, 增加了 NSEnumerationOptions 参数; 

(2) NSDictionary Key 过滤代码示例

示例代码​ : main.m 不同, 其它代码均相同;

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[[OCCat alloc] initWithName:@"Tom" age:18], @"Tom",
[[OCCat alloc] initWithName:@"Hank" age:26], @"Hank",
[[OCCat alloc] initWithName:@"Jerry" age:20], @"Jerry",
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

NSSet * set = [dictionary keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
OCCat * cat = (OCCat *)obj;
if(cat.age >= 20)
{
return YES;
}
return NO;
}];

NSLog(@"过滤后的key集合 : \n%@", set);

}
return 0;
}

-- ​执行结果​ : 

2015-10-19 13:59:42.931 06.NSDictionary[13750:303] {Tom = <OCCat [name = Tom, age = 18]> , Jerry = <OCCat [name = Jerry, age = 20]> , Hank = <OCCat [name = Hank, age = 26]> , }
2015-10-19 13:59:42.934 06.NSDictionary[13750:303] 过滤后的key集合 :
{(
Jerry,
Hank
)}
Program ended with exit code: 0

4. 自定义类作为 key

(1) 自定义类为 key 前提

自定义类为 key 基本要求​ : 

-- ​重写isEqual 和 hash 方法​ : isEqual : 和 hash : 方法必须正确重写, 即 isEqual 方法返回 YES 是, hash 方法返回的 hashCode 必须也相同;

-- ​实现 copyWithZone 方法​ : 尽量返回对象的不可变副本; 该策略是出于安全性考虑, 当多个 key-value 放入 NSDictionary 之后, 如果 key 可变导致 key 的hashCode 改变, 就会出现问题; 

(2) 自定义类为 key 代码示例

自定义类为 key 代码​ : 其它类代码相同, 只有 OCCat.m 与 main.m 不同;

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone] init];
cat.name = self.name;
cat.age = self.age;
return cat;
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
@"Tom", [[OCCat alloc] initWithName:@"Tom" age:18],
@"Hank", [[OCCat alloc] initWithName:@"Hank" age:26],
@"Jerry", [[OCCat alloc] initWithName:@"Jerry" age:20],
nil];

//自己实现的 NSDIctionary 打印方法
[dictionary toString];

}
return 0;
}



-- 

执行结果​ : 


2015-10-20 14:09:30.935 06.NSDictionary[15258:303] {<OCCat [name = Tom, age = 18]> = Tom , <OCCat [name = Hank, age = 26]> = Hank , <OCCat [name = Jerry, age = 20]> = Jerry , }
Program ended with exit code: 0

5. NSMutableDictionary 功能与用法

(1) NSMutableDictionary 简介

NSMutableDictionary 独有方法简介​ : 主要是比 NSDictionary 多个 增加 删除 键值对的方法;

-- ​"setObject : forKey : " 方法​ : 设置 key-value 键值对, 如果 key 与之前的不重复, 直接插入, 如果重复, 直接将 value 替换;

-- ​"setObject : forKeyedSubscript : " 方法​ : 通过下标方法设置键值对;

-- ​"addEntriesFromDictionary : " 方法​ : 将另一个 NSDictionary 中的值复制到当前的 NSMutableDictionary 中;

-- ​"setDictionary : " 方法​ : 用一个 NSDictionary 中的所有元素 替换另一个 NSDictionary 中的所有元素;

-- ​"removeObjectForKey : " 方法​ : 根据 key 删除 键值对;

-- ​"removeAllObjects : " 方法​ : 清空 NSDictionary;

-- ​"removeObjectForKeys : " 方法​ : 删除一个 NSArray 中包含的 key 的键值对; 

(2) NSMutableDictionary 方法示例

NSMutableDictionary 示例代码​ : 

-- ​代码​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSDictionary+toString.h"
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"Tom", [NSNumber numberWithInt:1],
@"Jerry", [NSNumber numberWithInt:2],
nil];
[dictionary toString];

//替换
NSLog(@"替换");
dictionary[[NSNumber numberWithInt:1]] = @"Hank";
[dictionary toString];

//增加
NSLog(@"增加");
dictionary[[NSNumber numberWithInt:3]] = @"Fuck";
[dictionary toString];

//添加整个字典到另一个字典
NSLog(@"添加整个字典到另一个字典");
NSDictionary * dic1 = [NSDictionary dictionaryWithObjectsAndKeys:
@"Obama", [NSNumber numberWithInt:4],
@"Bush", [NSNumber numberWithInt:5],
nil];
[dictionary addEntriesFromDictionary:dic1];
[dictionary toString];

//删除一部分
NSLog(@"删除一部分");
[dictionary removeObjectsForKeys:[NSArray arrayWithObjects:
[NSNumber numberWithInt:4], [NSNumber numberWithInt:5], nil]];
[dictionary toString];

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 15:04:01.100 06.NSDictionary[15426:303] {1 = Tom , 2 = Jerry , }
2015-10-20 15:04:01.102 06.NSDictionary[15426:303] 替换
2015-10-20 15:04:01.103 06.NSDictionary[15426:303] {1 = Hank , 2 = Jerry , }
2015-10-20 15:04:01.103 06.NSDictionary[15426:303] 增加
2015-10-20 15:04:01.104 06.NSDictionary[15426:303] {3 = Fuck , 1 = Hank , 2 = Jerry , }
2015-10-20 15:04:01.105 06.NSDictionary[15426:303] 添加整个字典到另一个字典
2015-10-20 15:04:01.106 06.NSDictionary[15426:303] {3 = Fuck , 2 = Jerry , 5 = Bush , 1 = Hank , 4 = Obama , }
2015-10-20 15:04:01.106 06.NSDictionary[15426:303] 删除一部分
2015-10-20 15:04:01.107 06.NSDictionary[15426:303] {3 = Fuck , 2 = Jerry , 1 = Hank , }
Program ended with exit code: 0

六. 谓词 NSPredicate


1. 谓词简介

(1) 谓词简介

谓词简介​ : 个人感觉 谓词比较像 Java 中的正则表达式;

-- ​作用​ : 谓词用于定义 逻辑条件, 用于 搜索 或 过滤内存中的数据, 尤其是 搜索过滤集合中的数据;

-- ​NSPredicate 子类​ : NSPredicate 有 3 个子类, NSComparisonPredicate , NSCompoundPredicate, NSExpression;

-- ​创建方法​ : 使用 NSPredicate 的 ​"predicateWithFormat :"​ 方法 创建 NSPredicate 对象;

-- ​没有占位符的谓词结果计算 ​: 直接使用 NSPredicate 的 evalueWithObject 方法计算谓词结果, 返回值是一个 BOOL 值;

-- ​有占位符的谓词结果计算​ : 调用 "predicateWithSubstitutionVariables" 方法为占位符参数设置参数值, 然后执行 evalueWithObject 方法计算结果;

-- ​同时完成两步的方法​ : NSPredicate 提供了一个 "evalueWithObject : substitutionVariables : " 方法可以同时替换占位符 和 计算结果;

(2) 谓词 代码简单示例

谓词代码示例​ : 

-- ​OCCat.h​ : 

//
// OCCat.h
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface OCCat : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) _name age : (int) _age;
- (NSComparisonResult) compare : (id) other;
@end

-- ​OCCat.m​ : 

//
// OCCat.m
// octopus
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import "OCCat.h"

@implementation OCCat
@synthesize name;
@synthesize age;

- (id) initWithName:(NSString *)_name age:(int)_age
{
self = [super init];
self.name = _name;
self.age = _age;
return self;
}

- (BOOL) isEqual : (id) other
{
//如果地址相同, 那么比较结果肯定相同
if(self == other)
{
return YES;
}

//对象对比之前首先保证类型相同
if([other class] == OCCat.class)
{
OCCat * cat = (OCCat *)other;
return [self.name isEqualToString:cat.name] && (self.age == cat.age);
}
return NO;
}

- (NSUInteger) hash
{
NSUInteger name_hash = [name hash];

return name_hash + age;
}

//%@ 打印的时候输出的内容
- (NSString *) description
{
return [NSString stringWithFormat:@"<OCCat [name = %@, age = %d]>", self.name, self.age];
}

- (id) copyWithZone : (NSZone *) zone
{
OCCat * cat = [[[self class] allocWithZone:zone] init];
cat.name = self.name;
cat.age = self.age;
return cat;
}

- (NSComparisonResult) compare:(id)other
{
if([other class] == OCCat.class)
{
OCCat * other_cat = (OCCat *)other;
if(self.age == other_cat.age)
{
return NSOrderedSame;
}
else if(self.age > other_cat.age)
{
return NSOrderedDescending;
}
else
{
return NSOrderedAscending;
}
}
return NSOrderedSame;
}
@end

-- ​main.m​ : 其它类 与 NSDictionary 中的示例相同;

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name like 'T*'"];
OCCat * cat = [[OCCat alloc] initWithName:@"Tom" age:18];
OCCat * cat2 = [[OCCat alloc] initWithName:@"Jerry" age:20];

NSLog(@"cat : %d, cat2 : %d", [predicate evaluateWithObject:cat], [predicate evaluateWithObject:cat2]);

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 16:21:32.998 06.NSDictionary[15545:303] cat : 1, cat2 : 0
Program ended with exit code: 0

2. 谓词过滤集合

(1) 集合过滤方法简介

谓词方法简介​ : 谓词遍历集合时, 使用谓词对集合中的元素进行过滤, 元素计算谓词返回 YES 才会被保留下来, 返回 NO, 该元素就会被删除;

-- ​"- (NSArray * ) filteredArrayUsingPredicate : (NSPredicate *) predicate :" 方法 ​: 使用谓词过滤 NSArray 集合, 返回过滤后的新集合;

-- ​"- (void) filterUsingPredicate : (NSPredicate *) predicate :" 方法​ : 使用谓词过滤 NSMutableArray 集合, 直接删除集合中的不合格的元素;

-- ​"- (NSSet * ) filteredSetUsingPredicate : (NSPredicate *) Predicate :" 方法​ : 使用谓词过滤 NSSet 集合, 返回一个新的集合;

-- ​"- (void) filterUsingPredicate : (NSPredicate * ) Predicate :" 方法​ : 过滤 NSMutableSet 集合, 直接删除不合格的元素;

(2) 集合过滤方法代码

示例代码​ : 

-- ​main.c​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSMutableArray * array = [NSMutableArray arrayWithObjects:
[NSNumber numberWithInt:10],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:30],
nil];
//过滤大于 15 的数字
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF > 15"];
[array filterUsingPredicate:predicate];
NSLog(@"过滤后的 array : \n%@", array);

NSSet * set = [NSSet setWithObjects:
[[OCCat alloc] initWithName:@"Tom" age:18],
[[OCCat alloc] initWithName:@"Jerry" age:20],
nil];
//过滤 name 包含 om 字符串的 NSSet
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"name CONTAINS 'om'"];
NSSet * filterSet = [set filteredSetUsingPredicate:predicate1];
NSLog(@"过滤后的 set : \n%@", filterSet);

}
return 0;
}

-- ​执行结果​ : 

2015-10-20 21:17:41.615 06.NSDictionary[15761:303] 过滤后的 array : 
(
20,
30
)
2015-10-20 21:17:41.617 06.NSDictionary[15761:303] 过滤后的 set :
{(
<OCCat [name = Tom, age = 18]>
)}
Program ended with exit code: 0

3. 谓词 占位符

(1) 谓词占位符参数

谓词支持的占位符​ : 

-- ​"%K" 占位符​ : 动态传入属性名;

-- ​"%@" 占位符​ : 动态设置属性值;

动态改变的属性值​ : 

-- ​示例​ : [NSPredicate PredicateWithFormat : @"name CATAINS $JAVA"], $JAVA 是动态改变值, 程序可以动态改变 $JAVA 值;

-- ​设置参数值​ : 调用 NSPredicate 的 predicateWithSubstitutionVariables : 设置参数值, 该方法返回 NSPredicate 对象;

-- ​计算结果​ : 调用 NSPredicate 的 evaluateWithObject : substitutionVariables : 完成参数计算结果;

(2) 谓词占位符参数 代码示例

代码示例​ : 

-- ​main.m​ : 

//
// main.m
// 06.NSDictionary
//
// Created by octopus on 15-10-18.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "OCCat.h"

int main(int argc, const char * argv[])
{

@autoreleasepool {

NSArray * array = [NSArray arrayWithObjects:
[[OCCat alloc] initWithName:@"Tom" age:18],
[[OCCat alloc] initWithName:@"Jerry" age:19],
[[OCCat alloc] initWithName:@"John" age:20],
[[OCCat alloc] initWithName:@"Fuck" age:13],
nil];
//谓词过滤, name 属性 包含 "o" 字符串的元素
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", @"name", @"o"];
NSArray * array1 = [array filteredArrayUsingPredicate:predicate];
NSLog(@"包含有 o 字符串集合 : \n%@", array1);


NSPredicate * predicateTemp = [NSPredicate predicateWithFormat:@"%K CONTAINS $JAVA", @"name"];
NSPredicate * predicate2 = [predicateTemp predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObjectsAndKeys:
@"o", @"JAVA", nil]];
NSArray * array2 = [array filteredArrayUsingPredicate:predicate2];
NSLog(@"array2 : \n%@", array2);

}
return 0;
}

-- ​执行结果​ : 

2015-10-21 09:40:18.593 06.NSDictionary[16254:303] 包含有 o 字符串集合 : 
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = John, age = 20]>"
)
2015-10-21 09:40:18.595 06.NSDictionary[16254:303] array2 :
(
"<OCCat [name = Tom, age = 18]>",
"<OCCat [name = John, age = 20]>"
)
Program ended with exit code: 0

4. 谓词 语法

谓词表达式​ : 使用谓词, 需要有谓词表达式, 该表达式会返回 BOOL 值;

(1) 比较运算符

比较运算符​ : 

-- ​"==" "=" 运算符​ : 判断左右两边表达式是否相等;

-- ​">=" "=>" 运算符​ : 左边 是否大于等于 右边 运算符; 

-- ​"<=" "=<" 运算符​ : 左边 是否小于等于 右边运算符;

-- ​">" 运算符​ : 左边 是否 大于 右边;

-- ​"<" 运算符​ : 左边 是否 小于 右边;

-- ​"!=" "<>" 运算符​ : 两个表达式是否不相等;

-- ​"BETWEEN" 运算符​ : 表达式格式 "BETWEEN {下限, 上限}", 表达式 大于等于 下限, 表达式 小于等于 上限;  

(2) 逻辑运算符

逻辑运算符​ : 

-- ​"AND" "&&" 运算符​ : 逻辑与;

-- ​"OR" "||" 运算符​ : 逻辑或;

-- ​"NOT" "!" 运算符 ​: 逻辑非;

(3) 逻辑运算符

逻辑运算符​ : 

-- ​"BEGINSWITH" 运算符​ : 字符串是否以指定字符串开头;

-- ​"ENDSSWITH" 运算符​ : 字符串是否以指定字符串结尾;

-- ​"CONTAINS" 运算符​ : 字符串是否包含指定字符串;

-- ​"LIKE" 运算符​ : 匹配指定字符串, 允许 "*" 和 "?" 通配符, * 代表多个字符, ? 代表一个字符;

-- ​"MATCHES" 运算符​ : 匹配正则表达式;

(4) 集合操作运算符

集合操作运算符​ : 

-- ​"ANY" "SOME" 运算符​ : 集合中任意一个元素满足条件, 返回 YES;

-- ​"ALL" 运算符​ : 集合中所有的元素满足条件 才 返回 YES;

-- ​"NONE" 运算符​ : 没有任何元素满足条件 返回 YES;

-- ​"IN" 运算符​ : 左边的表达式出现在右边的集合中 返回 YES;

-- ​"array[index]" 运算符​ : 返回 array 中 index 索引元素;

-- ​"array[FIRST]" 运算符​ : 返回 array 中的第一个元素;

-- ​"array[LAST]" 运算符​ : 返回 array 中最后一个元素;

-- ​"array[SIZE]" 运算符​ : 返回 array 中元素个数;

(5) 直接量

直接量​ : 

-- ​"FALSE" "NO"​ : 假逻辑;

-- ​"TRUE" "YES" ​: 真逻辑;

-- ​"NULL" "NIL"​ : 空值;

-- ​"SELF"​ : 对象本身;

-- ​"text" 'text' ​:  字符串;