IOS基础:OC的Foundation语法
原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 一、公共用法
- 1、加载及初始化类
- 2、分配内存空间及初始化对象
- 3、给对象发送消息(执行方法)
- 4、复制对象
- 5、获取Class
- 6、判断方法
- 7、重写对象的系统方法
- 8、SharedApplication
- 二、头部声明
- 1、常量和宏
- 2、枚举
- 3、属性关键字
- 三、基本数据类型
- 1、Null/nil
- 2、BOOL
- 3、NSNumber
- 4、NSData
- 5、CG类型
- 6、路径
- 四、字符串
- 1、范围
- 2、格式
- 3、拷贝
- 4、替换
- 5、比较
- 6、路径
- 7、字符串转变
- 8、字符串属性
- 9、可变字符串
- 10、富文本
- 五、集合
- 1、NSSet
- 2、NSDictionary
- 3、NSArray
- 六、NSDate
- 1、Date
- 2、Calendar
- 七、NSTimer
- 1、不重复的timer
- 2、重复的timer
- 3、Invocation + RunLoop
- 4、Fire Date + RunLoop
- 八、NSPredicate
- 1、谓词语法
- 2、正则表达式语法
- 3、包含关系
- 4、数据过滤
- 5、占位符
- 6、正则表达式
- 7、空值
- 8、复合谓词
- 9、Core Data中的使用
- Demo
- 参考文献
1、公共用法
1、加载及初始化类
// 运行时加载类或分类调用该方法, 每个类只会调用一次
+ (void)load;
// 类实例化使用前需要先初始化, 一个类调用一次, 如果子类没有实现该方法则会调用父类方法
+ (void)initialize;
load和initialize区别在于:
-
load
是只要类所在文件被引用就会被调用,而initialize
是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load
调用;但即使类文件被引用进来,但是没有使用,那么initialize
也不会被调用。 -
load
每个类只会调用一次,initialize
也只调用一次,但是如果子类没有实现initialize
方法则会调用父类的方法,因此作为父类的initialize
方法可能会调用多次。
2、分配内存空间及初始化对象
Student *student = [Student new];
Student *student2 = [[Student alloc] init];
Student *student3 = [[Student allocWithZone:nil] init];
创建新对象时,首先调用alloc
为对象分配内存空间,再调用init
初始化对象,如[[NSObject alloc] init]
;而new
方法先给新对象分配空间然后初始化对象,因此[NSObject new]
等同于[[NSObject alloc] init]
;关于allocWithZone
方法,官方文档解释该方法的参数是被忽略的,正确的做法是传nil
或者NULL
参数给它。
3、给对象发送消息(执行方法)
直接调用:
// 调用无参无返回值方法
[student running];
// 调用有参无返回值方法
[student readingWithText:@"Hello World!"];
// 调用有参有返回值方法
NSNumber *sum = [student sumWithNum:@(2) num2:@(3)];
我们通常都采用这种直接调用的方式,给对象发消息执行方法。这种方式调用编译时会自动校验方法、参数、返回值是否正确。因此我们必须在头文件中声明方法的使用。
使用performSelector
执行:
// 先判断对象是否能调用方法,再执行调用方法
if ([student respondsToSelector:@selector(running)]) {
// 调用无参无返回值方法
[student performSelector:@selector(running)];
}
if ([student respondsToSelector:@selector(readingWithText:)]) {
// 调用有参无返回值方法
[student performSelector:@selector(readingWithText:) withObject:@"Hello World"];
}
if ([student respondsToSelector:@selector(sumWithNum:num2:)]) {
// 调用有参有返回值方法
NSNumber *sum = [student performSelector:@selector(sumWithNum:num2:) withObject:@(2) withObject:@(8)];
}
使用performSelector:
是运行时系统负责去找方法,在编译时候不做任何校验;因此在使用时必须先使用respondsToSelector:
检查对象是否能调用方法,否则可能出现运行崩溃。performSelector:
常用于调用运行时添加的方法,即编译时不存在,但是运行时候存在的方法。另外需要注意的是performSelector:
系统提供最多接受两个参数的方法,而且参数和返回都是id
类型,并不支持基础数据类型(如:int
, float
等)。
使用IMP
指针调用:
// 创建SEL
SEL runSel = @selector(running);
SEL readSel = NSSelectorFromString(@"readingWithText:");
SEL sumSel = NSSelectorFromString(@"sumWithNum:num2:");
// 调用无参无返回值方法
IMP rumImp = [student methodForSelector:runSel];
void (*runFunc)(id, SEL) = (void *)rumImp;
runFunc(student, runSel);
// 调用有参无返回值方法
IMP readImp = [[student class] instanceMethodForSelector:readSel];
void (*speakFunc)(id, SEL, NSString *) = (void *)readImp;
speakFunc(student, readSel, @"Hello World");
// 调用有参有返回值方法
IMP sumImp = [student methodForSelector:sumSel];
NSNumber *(*sumFunc)(id, SEL, NSNumber *, NSNumber *) = (void *)sumImp;
NSNumber *sum3 = sumFunc(student, sumSel, @(6), @(6));
SEL
是方法的索引。IMP
是函数指针,指向方法的地址。SEL
与IMP
是一一对应的关系,因此我们可以通过修改对应关系达到运行时方法交换的目的。
创建SEL
对象两种方法:
- 使用
@selector()
创建 - 使用
NSSelectorFromString()
创建
获取方法IMP
指针两种方法:
-
- (IMP)methodForSelector:(SEL)aSelector;
实例方法 -
+ (IMP)instanceMethodForSelector:(SEL)aSelector;
类方法
4、复制对象
copy
拷贝为不可变对象,mutableCopy
拷贝为可变对象。虽然copy
对静态对象只是引用计数加1,但是并不影响我们对复制前后的对象进行使用。需要注意的是对于容器对象而言,这两个方法只是复制了容器本身,对容器中包含的对象只是简单的指针引用,并没有深层复制。
// 复制人物
- (instancetype)copyWithZone:(NSZone *)zone
{
Person *person = [[Person alloc] init];
person.firstName = self.firstName;
person.lastName = self.lastName;
return person;
}
// 使用复制
- (void)useCopy
{
// 两个源数组
NSArray *sourceArrayI = [NSArray arrayWithObjects:@"I", @"II", nil];
NSMutableArray *sourceArrayM = [NSMutableArray arrayWithObjects:@"M", @"MM", nil];
// 两个copy
NSArray *copyArrayI = [sourceArrayI copy];
NSArray *copyArrayM = [sourceArrayM copy];
// 两个mutableCopy
NSMutableArray *mutableArrayI = [sourceArrayI mutableCopy];
NSMutableArray *mutableArrayM = [sourceArrayM mutableCopy];
// 对象拷贝
Person *aPerson = [[Person alloc] init];
Person *copyPerson = [aPerson copy];
NSLog(@"源对象为:%@",aPerson);
NSLog(@"copy对象为:%@",copyPerson);
NSLog(@"copy对象的姓名为:%@", [copyPerson fullName]);
}
输出结果为:
2020-10-20 17:10:50.942504+0800 BasicGrammarDemo[27278:4928170] 源对象为:<Person: 0x600002515320>
2020-10-20 17:10:50.942579+0800 BasicGrammarDemo[27278:4928170] copy对象为:<Person: 0x600002515340>
2020-10-20 17:10:50.942638+0800 BasicGrammarDemo[27278:4928170] copy对象的姓名为:LuoMei Bai
5、获取Class
// 获取类
Class curClass1 = [student class];
Class curClass2 = [ZMStudent class];
// 获取父类
Class supClass1 = [student superclass];
Class supClass2 = [ZMStudent superclass];
6、判断方法
声明两个继承关系的类
@interface Person : NSObject
- (void)run;
@end
@interface Student : Person
@end
@implementation Person
- (void)run
{
NSLog(@"滚 能换一种说法吗? 蹿吧,孩儿。能文明一点吗?去吧,皮卡丘。能高大上一点吗?奔跑吧,兄弟。能再上档次点吗?世界这么大,你怎么不去看看。能有点诗意吗?你来人间一趟,你要看看太阳。能有点鼓动性吗?奔涌吧,后浪!");
}
@end
@implementation Student
@end
使用判断方法
- (void)useJudgment
{
// 初始化对象
Person *person = [Person new];
Student *studentXie = [Student new];
Student *studentFan = studentXie;
// 判断对象是否继承自NSObject
if ([studentXie isProxy])
{
NSLog(@"student对象是继承自NSObject类");
}
// 判断两个对象是否相等
if ([studentXie isEqual:studentFan])
{
NSLog(@"studentXie对象与studentFan对象相等,两位同学可能是同一个人");
}
// 判断对象是否是指定类
if ([person isKindOfClass:[Person class]])
{
NSLog(@"person对象是Person类,即人是人类");
}
// 判断对象是否是指定类或子类
if ([studentXie isKindOfClass:[Person class]])
{
NSLog(@"studentXie对象是Person类的子类,谢同学再颓废没有生气也是个活生生的人呀");
}
// 判断某个类是否是另一个类的子类
if ([Student isSubclassOfClass:[Person class]])
{
NSLog(@"Student类是Person类的子类");
}
// 判判断对象是否遵从协议
if ([studentXie conformsToProtocol:@protocol(NSObject)])
{
NSLog(@"studentXie对象遵循NSObject协议");
}
// 判断类是否遵从给定的协议
if ([Student conformsToProtocol:@protocol(NSObject)])
{
NSLog(@"Student类遵循NSObject协议");
}
// 判断对象是否能够调用给定的方法
if ([studentXie respondsToSelector:@selector(run)])
{
NSLog(@"student对象可以调用run方法");
}
// 判断实例是否能够调用给定的方法
if ([Student instancesRespondToSelector:@selector(run)])
{
NSLog(@"Student类可以调用run方法");
}
}
输出结果
2020-10-20 16:46:46.061658+0800 BasicGrammarDemo[26898:4909800] studentXie对象与studentFan对象相等,两位同学可能是同一个人
2020-10-20 16:46:46.061769+0800 BasicGrammarDemo[26898:4909800] person对象是Person类,即人是人类
2020-10-20 16:46:46.061831+0800 BasicGrammarDemo[26898:4909800] studentXie对象是Person类的子类,谢同学再颓废没有生气也是个活生生的人呀
2020-10-20 16:46:46.061902+0800 BasicGrammarDemo[26898:4909800] Student类是Person类的子类
2020-10-20 16:46:46.061988+0800 BasicGrammarDemo[26898:4909800] studentXie对象遵循NSObject协议
2020-10-20 16:46:46.062055+0800 BasicGrammarDemo[26898:4909800] Student类遵循NSObject协议
2020-10-20 16:46:46.062127+0800 BasicGrammarDemo[26898:4909800] student对象可以调用run方法
2020-10-20 16:46:46.062196+0800 BasicGrammarDemo[26898:4909800] Student类可以调用run方法
7、重写对象的系统方法
a、重写系统方法
@interface Animal : NSObject <NSCopying>
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) NSString *age;
@end
@implementation Animal
// 重写isEqual:
- (BOOL)isEqual:(id)object
{
// 自身
if (self == object)
{
return YES;
}
// 类型相同
if ([object class] == [Animal class])
{
// 转化
Animal *target = (Animal *)object;
// 设置判断标准
BOOL result = ([self.name isEqualToString:target.name] && (self.age == target.age));
return result;
}
return NO;
}
// 重写hash
- (NSUInteger)hash
{
NSUInteger nameHash = (self.name == nil ? 0 : [self.name hash]);
NSUInteger ageHash = (self.age == nil ? 0 : [self.name hash]);
return nameHash * 31 + ageHash;
}
// 重写description
- (NSString *)description
{
return [NSString stringWithFormat:@"name:%@,age:%@", self.name,self.age];
}
// 重写copyWithZone
- (id)copyWithZone:(NSZone *)zone
{
Animal *new = [[[self class] allocWithZone:zone] init];
new.name = self.name;
new.age = self.age;
return new;
}
@end
b、调用方式
- (void)useCover
{
Animal *animal = [[Animal alloc] init];
animal.name = @"xiejiapei";
animal.age = @"23";
NSLog(@"重写了description后,源对象为:%@",[animal description]);
NSLog(@"源对象hash为:%lu",(unsigned long)[animal hash]);
Animal *copyAnimal = [animal copy];
NSLog(@"copy对象为:%@",copyAnimal);
if ([copyAnimal isEqual:animal])
{
NSLog(@"两个对象相等");
}
}
c、输出结果
2020-11-03 10:05:35.037203+0800 FoundationDemo[93106:3989340] 重写了description后,源对象为:name:xiejiapei,age:23
2020-11-03 10:05:35.037308+0800 FoundationDemo[93106:3989340] 源对象hash为:3770145254414366752
2020-11-03 10:05:35.037378+0800 FoundationDemo[93106:3989340] copy对象为:name:xiejiapei,age:23
2020-11-03 10:05:35.037432+0800 FoundationDemo[93106:3989340] 两个对象相等
8、SharedApplication
- (void)useSharedApplication
{
// 获得UIApplicationDelegate对象
[[UIApplication sharedApplication] delegate];
// 获得UIWindow对象
[[UIApplication sharedApplication] keyWindow];
// 打开设置界面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
// 远程的控制相关
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
// 不让手机休眠
[UIApplication sharedApplication].idleTimerDisabled = YES;
// 后台剩余时间
NSTimeInterval remainTime = [[UIApplication sharedApplication] backgroundTimeRemaining];
NSLog(@"剩余时间 = %f",remainTime);
// 后台刷新的状态
[[UIApplication sharedApplication] backgroundRefreshStatus];
// 开启/关闭任务
[[UIApplication sharedApplication] beginBackgroundTaskWithName:@"task" expirationHandler:^{
}];
[[UIApplication sharedApplication] endBackgroundTask:1];
}
二、头部声明
1、常量和宏
- 宏在预编译时处理(宏在编译开始之前就会被替换),而
const
会在编译时被处理 -
#define
宏没有类型,宏不做任何类型检查,不会报编译错误,只是替换,而const
常量有具体的类型,会编译检查,会报编译错误 - 宏能定义一些函数,方法,而
const
不能 - 使用大量宏,容易造成编译时间久,因为每次都需要重新替换
- 宏定义时不分配内存,变量定义时分配内存
- 预编译期间进行宏替换,分配内存,再进行宏替换,又一次分配内存,内存中有若干个拷贝。
const doulbe Pi
——double i=Pi;
此时为Pi
分配内存,以后不再分配!只有一份拷贝(因为是全局的只读变量,存在静态区)
// const常量:后跟谁定谁
const NSString *constString = @"谢佳培";
NSString *const stringConst = @"甜的";
// 等价于char *s1; char s2
#define MyString char *s1,s2
// 常用宏定义的颜色、字体字号
#define ROW_SIZE 20
#define Blue [UIColor colorWithRed:(0x##r)/255.0 green:(0x##g)/255.0 blue:(0x##b)/255.0 alpha:1]
// 宏定义获取rootViewController
#define RootVC [UIApplication sharedApplication].delegate.window.rootViewController
// 宏定义获取当前的界面
#define TopVC ([RootVC isKindOfClass:[UITabBarController class]]?[((UITabBarController *)RootVC).selectedViewController topViewController]:RootVC)
2、枚举
-
define
写在方法/函数中则作用域从写的地方开始有效,直至使用#undef
(不写此指令则后面一直有效),typedef
写在方法/函数中则作用域,只在此方法/函数中有效。 -
typedef
是类型替换,直接参与编译,而define
只是简单的文本替换。
C语言格式
// 给NSTimeInterval取别名为MyTime
typedef NSTimeInterval MyTime;
// c语言格式,给Person结构体取别名为MyPerson
// 使用:MyPerson p = {"jack"};
typedef struct Person {
char *name;
} MyPerson;
// c语言格式,给Gender枚举取别名为MyGender
// 使用:MyGender g = Man;
typedef enum Gender {
Man,
Woman
} MyGender;
OC语言格式
typedef NS_ENUM(NSInteger, NumberType)
{
NumberTypeInt = 0,
NumberTypeFloat = 1,
NumberTypeDouble = 2
};
NumberType type = NumberTypeInt;
typedef NS_OPTIONS(NSUInteger, TMEnumTest)
{
TMEnumTestOne = 0, // 0
TMEnumTestTwo = 1 << 0, // 1
TMEnumTestThree = 1 << 1, // 2
TMEnumTestFour = 1 << 2, // 4
};
TMEnumTest test = TMEnumTestTwo | TMEnumTestThree;
typedef NS_OPTIONS(NSUInteger, LifeRoleOptions)
{
LifeRoleOptionsFather = 1UL << 0,
LifeRoleOptionsSon = 1UL << 1,
LifeRoleOptionsHusband = 1UL << 3,
};
LifeRoleOptions lifeRole = LifeRoleOptionsFather | LifeRoleOptionsSon;
// 给block取别名MyBlock
typedef void(^MyBlock) (int a,int b);
使用方式
- (void)useTypedef
{
// 添加TMEnumTestFour到test中
test += TMEnumTestFour;
// 将TMEnumTestThree从test中去除
test -= TMEnumTestThree;
// 判断 TMEnumTestFour枚举 是否被包含
if (test & TMEnumTestFour)
{
NSLog(@"数字是:四");
}
// 判断 TMEnumTestThree枚举 是否被包含
if (test & TMEnumTestThree)
{
NSLog(@"数字是:三");
}
if (lifeRole & LifeRoleOptionsFather)
{
NSLog(@"人生角色:父亲");
}
if (lifeRole & LifeRoleOptionsHusband)
{
NSLog(@"人生角色:丈夫");
}
}
输出结果
2020-10-20 15:24:20.763915+0800 BasicGrammarDemo[25511:4841344] 数字是:四
2020-10-20 15:24:20.764021+0800 BasicGrammarDemo[25511:4841344] 人生角色:父亲
3、属性关键字
类型
- atomic:系统默认,声明的属性保证赋值和获取是线程安全的,不保证添加和移除是线程安全的(如数组)
- noatomic:经常声明
- retain/strong
-
assign/unsafe_unretained:修饰基本数据类型,如
int
、Bool
。修饰对象类型时候,不改变其引用计数。对象释放后,会产生悬垂指针,仍访问会产生内存泄露。 -
weak:不改变修饰对象的引用计数,对象释放后,自动置为
nil
。 -
copy浅拷贝和深拷贝的区别:是否开辟了新的内存空间,是否影响了引用计数。可变对象
copy
后是NSArray
不可以调用add delete
等方法。只有不可变对象的copy
是浅拷贝,其他都是深拷贝。
属性声明
//默认关键字
@property (atomic, strong, readwrite) NSString *firstName;
@property (readonly, getter=isShit) BOOL shit;
@property (nonatomic, strong) NSArray *vcTitles;
@property (nonatomic, strong) NSArray<NSArray *> *pickerData;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) personBlock runFinishBlock;
@property (nonatomic, weak) id<WorkProtocol> delegate;
@property (nonatomic, weak) id<CountToolDataSource> dataSource;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) BOOL bodyTextChanged;
@property (nonatomic, assign) NSTimeInterval created;
使用演示
@interface PersonClass : NSObject
@property (nonatomic, strong) NSObject *objStrong;
@property (nonatomic, weak) NSObject *objWeak;
@property (nonatomic, assign) NSObject *objAssign;
@property (nonatomic, copy) NSString *objCopy;
@end
// 使用属性关键字
- (void)useAttributeKey
{
PersonClass *aPerson = [[PersonClass alloc] init];
aPerson.objStrong = [[NSObject alloc] init];
// 系统会警告,但不会报错
aPerson.objWeak = [[NSObject alloc] init];
aPerson.objAssign = [[NSObject alloc] init];
NSMutableString *testStr = [[NSMutableString alloc] initWithString:@"我知道什么呢?"];
aPerson.objCopy = testStr;
[aPerson setObjCopy:testStr];
[testStr appendString:@"什么都知道"];
// 正确的方式
NSLog(@"objWeak %@", aPerson.objStrong);
// weak会释放为null
NSLog(@"objWeak %@", aPerson.objWeak);
// Assign会崩溃
// NSLog(@"objAssign %@", aPerson.objAssign);
// Copy后,原字符串改变对新字符串无影响
NSLog(@"testStr %@", testStr);
NSLog(@"objCopy %@", aPerson.objCopy);
}
输出结果
2020-10-20 15:38:17.996696+0800 BasicGrammarDemo[25777:4854926] objWeak <NSObject: 0x60000006c1b0>
2020-10-20 15:38:17.996794+0800 BasicGrammarDemo[25777:4854926] objWeak (null)
2020-10-20 15:38:17.996872+0800 BasicGrammarDemo[25777:4854926] testStr 我知道什么呢?什么都知道
2020-10-20 15:38:17.996936+0800 BasicGrammarDemo[25777:4854926] objCopy 我知道什么呢?
三、基本数据类型
1、Null/nil
// 默认值: NO/0/nil
Person *aPerson = nil;
aPerson.age // 0
// 用在不能在数组和词典对象中放入nil ,又确实需要一个特殊的对象来表示空值
+ (NSNull *) null
2、BOOL
BOOL hidden = YES;
BOOL bigger = 0 > 1;
if (-1)
{
NSLog(@"not 0 = YES");
}
NSObject *boolObj = [[NSObject alloc] init];
if (boolObj)
{
NSLog(@"not nil = YES");
}
输出结果为:
2020-10-21 11:40:25.715805+0800 BasicGrammarDemo[31446:5105441] not 0 = YES
2020-10-21 11:40:25.715873+0800 BasicGrammarDemo[31446:5105441] not nil = YES
3、NSNumber
// 用语法糖进行声明,可转换为多种数据类型
NSNumber *intNumber = @(-1);
NSNumber *boolNumber = @(YES);
NSNumber *charNumber = @('A');
NSLog(@"int(-1)值:%@,bool(YES)值:%@ ,char(A)值:%@", intNumber, boolNumber, charNumber);
NSLog(@"字面A的charValue值:%d,stringValue值:%@,intValue值:%d", charNumber.charValue, charNumber.stringValue, charNumber.intValue);
输出结果为:
2020-10-21 11:44:24.847241+0800 BasicGrammarDemo[31501:5108050] int(-1)值:-1,bool(YES)值:1 ,char(A)值:65
2020-10-21 11:44:24.847298+0800 BasicGrammarDemo[31501:5108050] 字面A的charValue值:65,stringValue值:65,intValue值:65
4、NSData
NSString *dataString = @"XieJiaPei";
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"string(XieJiaPei) 转化为 data:%@", data);
NSData *zeroData = [NSData data];
NSLog(@"空数据为:%@", zeroData);
NSMutableData *appendData = [zeroData mutableCopy];
[appendData appendData:data];
NSLog(@"在空数据后追加数据后结果为:%@", appendData);
输出结果为:
2020-10-21 13:44:31.226384+0800 BasicGrammarDemo[32605:5160936] string(XieJiaPei) 转化为 data:{length = 9, bytes = 0x5869654a6961506569}
2020-10-21 13:44:31.226465+0800 BasicGrammarDemo[32605:5160936] 空数据为:{length = 0, bytes = 0x}
2020-10-21 13:44:31.226546+0800 BasicGrammarDemo[32605:5160936] 在空数据后追加数据后结果为:{length = 9, bytes = 0x5869654a6961506569}
5、CG类型
- (void)useCG
{
// 状态栏高度
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
NSLog(@"状态栏高度:%f",statusBarHeight);
// 如何把一个CGPoint存入数组里
CGPoint point = CGPointMake(0, 0);
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:NSStringFromCGPoint(point), nil];
point = CGPointFromString(array[0]);
NSLog(@"如何把一个CGPoint存入数组里: %@",array);
}
输出结果为:
2020-10-30 13:40:44.198593+0800 FoundationDemo[42880:1608020] 状态栏高度:44.000000
2020-10-30 13:40:44.198740+0800 FoundationDemo[42880:1608020] 如何把一个CGPoint存入数组里: (
"{0, 0}"
)
四、字符串
1、范围
a、NSMakeRange
NSRange range = NSMakeRange(2, 4);
NSString *fullString = @"abcdefghijk";
NSString *subString = [fullString substringWithRange:range];
NSLog(@"原字符串为abcdefghijk,其(2,4)范围内的子字符串为:%@", subString);
输出结果为:
2020-10-21 13:52:18.515144+0800 BasicGrammarDemo[32785:5169598] 原字符串为abcdefghijk,其(2,4)范围内的子字符串为:cdef
b、substringToIndex
NSString *intString = @"456789";
NSString *charString = @"abcdef";
NSString *chineseString = @"中文哈哈哈哈";
NSString *subIntString = [intString substringToIndex:2];
NSString *subCharString = [charString substringToIndex:2];
NSString *subChineseString = [chineseString substringToIndex:2];
NSLog(@"substringToIndex:2,456789的子串为:%@,abcdef的子串为:%@,中文哈哈哈哈的子串为:%@", subIntString,subCharString,subChineseString);
输出结果为:
2020-10-21 13:57:36.238543+0800 BasicGrammarDemo[32871:5174143] substringToIndex:2,456789的子串为:45,abcdef的子串为:ab,中文哈哈哈哈的子串为:中文
c、substringFromIndex
NSString *subFromString = [chineseString substringFromIndex:2];
NSLog(@"原字符串为中文哈哈哈哈,FromIndex:2范围内的子字符串为:%@", subFromString);
输出结果为:
2020-10-21 14:14:07.313580+0800 BasicGrammarDemo[33183:5188958] 原字符串为中文哈哈哈哈,FromIndex:2范围内的子字符串为:哈哈哈哈
2、格式
a、stringWithFormat
NSString *stringWithFormat = [NSString stringWithFormat:@"字符串为: %@, 两位小数的浮点数为: %1.2f",@"XieJiaPei", 31415.9265];
NSLog(@"带格式的字符串 = %@", stringWithFormat);
输出结果为:
2020-10-21 14:04:51.764665+0800 BasicGrammarDemo[33017:5180791] 带格式的字符串 = 字符串为: XieJiaPei, 两位小数的浮点数为: 31415.93
b、stringByAppendingFormat
NSNumber *number = @12345;
NSDictionary *dictionary = @{@"date": [NSDate date]};
NSString *baseString = @"Test: ";
NSString *stringByAppendingFormat = [baseString stringByAppendingFormat:@"数字: %@, 字典: %@", number, dictionary];
NSLog(@"追加格式字符串 = %@", stringByAppendingFormat);
输出结果为:
2020-10-21 14:09:38.901710+0800 BasicGrammarDemo[33102:5185253] 追加格式字符串 = Test: 数字: 12345, 字典: {
date = "2020-10-21 06:09:38 +0000";
}
3、拷贝
NSString *copyIntString = [intString copy];
NSString *copyCharString = [charString copy];
NSString *copyChineseString = [chineseString copy];
NSLog(@"复制后的字符串,%@,%@,%@", copyIntString,copyCharString,copyChineseString);
输出结果为:
2020-10-21 14:01:51.381827+0800 BasicGrammarDemo[32960:5177962] 复制后的字符串,456789,abcdef,中文哈哈哈哈
4、替换
NSString *replaceChineseString = [chineseString stringByReplacingOccurrencesOfString:@"哈" withString:@"好"];
NSLog(@"原字符串为中文哈哈哈哈,替换后为:%@", replaceChineseString);
NSString *pureChineseString = [chineseString stringByReplacingOccurrencesOfString:@"哈" withString:@""];
NSLog(@"原字符串为中文哈哈哈哈,用替换的方式进行删除后为:%@", pureChineseString);
输出结果为:
2020-10-21 14:18:03.822172+0800 BasicGrammarDemo[33238:5192253] 原字符串为中文哈哈哈哈,替换后为:中文好好好好
2020-10-21 14:18:03.822240+0800 BasicGrammarDemo[33238:5192253] 原字符串为中文哈哈哈哈,用替换的方式进行删除后为:中文
5、比较
NSString *abc = @"abc";
NSString *aBc = @"aBc";
NSString *aB = @"aB";
NSComparisonResult abcOrder = [abc compare:aBc];
NSComparisonResult aBOrder = [aB compare:aBc];
NSLog(@"abc compare:aBc的结果为:%ld,即abc > aBc",(long)abcOrder);
NSLog(@"aB compare:aBc的结果为:%ld,即aB < aBc",(long)aBOrder);
输出结果为:
2020-10-21 14:22:18.913094+0800 BasicGrammarDemo[33347:5197161] abc compare:aBc的结果为:1,即abc > aBc
2020-10-21 14:22:18.913165+0800 BasicGrammarDemo[33347:5197161] aB compare:aBc的结果为:-1,即aB < aBc
6、路径
a、hasPrefix/hasSuffix
if ([aBc hasSuffix:@"Bc"])
{
NSLog(@"aBc的后缀为Bc");
}
if ([aBc hasPrefix:@"aB"])
{
NSLog(@"aBc的前缀为aB");
}
输出结果为:
2020-10-21 14:25:09.571763+0800 BasicGrammarDemo[33434:5201268] aBc的后缀为Bc
2020-10-21 14:25:09.571853+0800 BasicGrammarDemo[33434:5201268] aBc的前缀为aB
b、stringByAppendingPathComponent
NSString *homePath = NSHomeDirectory();// 能够访回当前用户的主目录
NSString *workPath = [homePath stringByAppendingPathComponent:@"LuckCoffee"];
NSLog(@"瑞幸咖啡的存储路径为:%@", workPath);
输出结果为:
2020-10-21 14:28:37.083043+0800 BasicGrammarDemo[33522:5205708] 瑞幸咖啡的存储路径为:/Users/xiejiapei/Library/Developer/CoreSimulator/Devices/8D07F1D9-24C5-45A2-8AA2-3AB9EF752D6F/data/Containers/Data/Application/202BCFAD-50E8-499B-833C-93426D5EAB1E/LuckCoffee
c、lastPathComponent/pathExtension
NSString *filePath = @"/tmp/image/cat.tiff";
NSLog(@"路径为:/tmp/image/cat.tiff,最后一个部分为:%@,文件的扩展名为:%@",[filePath lastPathComponent],[filePath pathExtension]);
输出结果为:
2020-10-21 15:14:28.535638+0800 BasicGrammarDemo[34137:5237242] 路径为:/tmp/image/cat.tiff,最后一个部分为:cat.tiff,文件的扩展名为:tiff
7、字符串转变
a、componentsSeparatedByString / componentsJoinedByString
// 分割
NSArray *pathArray = [homePath componentsSeparatedByString:@"/"];
NSLog(@"NSHomeDirectory的路径为:%@", homePath);
NSLog(@"路径转变为数组后为:%@", pathArray);
// 拼接
NSString *joinPath = [pathArray componentsJoinedByString:@"/"];
NSLog(@"将数组拼接成为路径:%@",joinPath);
输出结果为:
2020-10-21 15:25:32.289578+0800 BasicGrammarDemo[34365:5248464] NSHomeDirectory的路径为:/Users/xiejiapei/Library/Developer/CoreSimulator/Devices/8D07F1D9-24C5-45A2-8AA2-3AB9EF752D6F/data/Containers/Data/Application/E1A549FF-396C-402B-934A-35BB04F60A1A
2020-10-21 15:25:32.289679+0800 BasicGrammarDemo[34365:5248464] 路径转变为数组后为:(
"",
Users,
xiejiapei,
Library,
Developer,
CoreSimulator,
Devices,
"8D07F1D9-24C5-45A2-8AA2-3AB9EF752D6F",
data,
Containers,
Data,
Application,
"E1A549FF-396C-402B-934A-35BB04F60A1A"
)
2020-10-21 15:25:32.289762+0800 BasicGrammarDemo[34365:5248464] 将数组拼接成为路径:/Users/xiejiapei/Library/Developer/CoreSimulator/Devices/8D07F1D9-24C5-45A2-8AA2-3AB9EF752D6F/data/Containers/Data/Application/E1A549FF-396C-402B-934A-35BB04F60A1A
b、initWithData
NSString *name = @"XieJiaPei";
// 将NSString转化为NSData
NSData *data = [name dataUsingEncoding:NSUTF8StringEncoding];
// 用存储在data中的二进制数据来初始化NSString对象
NSString *dataName = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"用存储在data中的二进制数据来初始化NSString对象,结果为:%@",dataName);
输出结果为:
2020-10-21 15:14:28.536003+0800 BasicGrammarDemo[34137:5237242] 用存储在data中的二进制数据来初始化NSString对象,结果为:XieJiaPei
c、把NSArray集合转换为格式字符串
NSArray *array = @[@"xie",@"jia",@"pei",@"fan",@"yi",@"cheng",@"lin",@"feng",@"mian"];
NSMutableString *result = [NSMutableString stringWithString:@"["];
for (id object in array)
{
[result appendString:[object description]];
[result appendString:@","];
}
// 去掉字符串最后的两个字符
[result deleteCharactersInRange:NSMakeRange(result.length - 2, 2)];
[result appendString:@"]"];
NSLog(@"把NSArray集合转换为字符串:%@",result);
输出结果为:
2020-10-30 16:49:02.894530+0800 FoundationDemo[46760:1747913] 把NSArray集合转换为字符串:[xie,jia,pei,fan,yi,cheng,lin,feng,mia]
8、字符串属性
// 字符串对象内部使用Unicode 编码,返回C语言字符串的指针
NSLog(@"Unicode 编码:%s",[name UTF8String]);
// 小写与大写
NSLog(@"原字符串为:XieJiaPei,小写结果为:%@",[name lowercaseString]);
NSLog(@"原字符串为:XieJiaPei,大写结果为::%@",[name uppercaseString]);
NSLog(@"原字符串为:XieJiaPei,首字母变为大写结果为::%@",[name capitalizedString]);
// 分别被用来把NSString类型的字符串转为float、int、NSinteger和BOOL类型的数值
NSLog(@"原字符串为:414.5678,floatValue值为:%f",[@"414.5678" floatValue]);
NSLog(@"原字符串为:512,intValue值为:%d",[@"512" intValue]);
NSLog(@"原字符串为:1024,integerValue值为:%ld",(long)[@"1024" integerValue]);
NSLog(@"原字符串为:OK,boolValue值为:%ld",(long)[@"2" boolValue]);
输出结果为:
2020-10-21 15:16:56.468275+0800 BasicGrammarDemo[34195:5239924] Unicode 编码:XieJiaPei
2020-10-21 15:16:56.468392+0800 BasicGrammarDemo[34195:5239924] 原字符串为:XieJiaPei,小写结果为:xiejiapei
2020-10-21 15:16:56.468487+0800 BasicGrammarDemo[34195:5239924] 原字符串为:XieJiaPei,大写结果为::XIEJIAPEI
2020-10-21 15:16:56.468600+0800 BasicGrammarDemo[34195:5239924] 原字符串为:XieJiaPei,首字母变为大写结果为::Xiejiapei
2020-10-21 15:16:56.468715+0800 BasicGrammarDemo[34195:5239924] 原字符串为:414.5678,floatValue值为:414.567810
2020-10-21 15:16:56.468827+0800 BasicGrammarDemo[34195:5239924] 原字符串为:512,intValue值为:512
2020-10-21 15:16:56.468971+0800 BasicGrammarDemo[34195:5239924] 原字符串为:1024,integerValue值为:1024
2020-10-21 15:16:56.469081+0800 BasicGrammarDemo[34195:5239924] 原字符串为:OK,boolValue值为:1
9、可变字符串
// 随着字符串的变化而自动扩展内存,所以capacity不需要非常精密
NSMutableString* mutableString = [[NSMutableString alloc] initWithCapacity:20];
// 在原来的字符串尾部添加,返回void,不产生新字符串
[mutableString appendString:@"所谓平庸"];
// 在原来的字符串尾部添加格式化字符串
[mutableString appendFormat:@"是在于认清%i个人的限度,而安于这个限度。",1];
// 插入字符串
[mutableString insertString:@"," atIndex:4];
// 替换
[mutableString replaceCharactersInRange:NSMakeRange(2, 2) withString:@"幸福"];
NSLog(@"可变字符串为:%@",mutableString);
输出结果为:
2020-10-21 15:29:30.122108+0800 BasicGrammarDemo[34466:5253526] 可变字符串为:所谓幸福,是在于认清1个人的限度,而安于这个限度。
10、富文本
下划线NSString *singleLineText = @"Single Line";
// 下划线
NSAttributedString *singleLineTextAttr = [[NSAttributedString alloc] initWithString:singleLineText attributes:@{NSUnderlineStyleAttributeName: @(1)}];
UILabel *singleLineLabel = [[UILabel alloc] initWithFrame:CGRectMake(150, 100, 100, 50)];
singleLineLabel.attributedText = singleLineTextAttr;
[self.view addSubview:singleLineLabel];
五、集合
1、NSSet
a、集合
- (void)set
{
NSSet *set = [NSSet setWithObjects:@"xie",@"jia",@"pei", nil];
NSSet *newSet = [NSSet setWithSet:set];
NSSet *differenceSet = [NSSet setWithObjects:@"xie",@"liu",@"ying", nil];
NSSet *deepCopySet = [[NSSet alloc] initWithSet:set copyItems:YES];
NSLog(@"如果是深拷贝,所有元素必须符合NSCoping协议,拷贝后集合为:%@",deepCopySet);
NSLog(@"集合中元素个数:%lu",(unsigned long)[set count]);
set = [set setByAddingObject:@"love"];
NSLog(@"将添加单个元素后生成的新集合赋给set:%@",set);
set = [set setByAddingObjectsFromSet:newSet];
NSLog(@"添加多个元素,相当于并集:%@",set);
[set intersectsSet:differenceSet];
NSLog(@"是否有交集:%@",set);
[set isSubsetOfSet:differenceSet];
NSLog(@"是否有子集:%@",set);
[set containsObject:@"xie"];
NSLog(@"集合中是否包含元素:%@",set);
[set anyObject];
NSLog(@"随取元素:%@",set);
NSSet *filteredSet = [set objectsPassingTest:^BOOL(id _Nonnull obj, BOOL * _Nonnull stop){
return ([obj isEqualToString:@"xie"]);
}];
NSLog(@"过滤集合:%@",filteredSet);
}
输出结果为:
2020-11-03 09:30:14.902811+0800 FoundationDemo[92415:3957705] 如果是深拷贝,所有元素必须符合NSCoping协议,拷贝后集合为:{(
xie,
jia,
pei
)}
2020-11-03 09:30:14.902907+0800 FoundationDemo[92415:3957705] 集合中元素个数:3
2020-11-03 09:30:14.902984+0800 FoundationDemo[92415:3957705] 将添加单个元素后生成的新集合赋给set:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903052+0800 FoundationDemo[92415:3957705] 添加多个元素,相当于并集:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903110+0800 FoundationDemo[92415:3957705] 是否有交集:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903186+0800 FoundationDemo[92415:3957705] 是否有子集:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903257+0800 FoundationDemo[92415:3957705] 集合中是否包含元素:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903325+0800 FoundationDemo[92415:3957705] 随取元素:{(
jia,
xie,
pei,
love
)}
2020-11-03 09:30:14.903401+0800 FoundationDemo[92415:3957705] 过滤集合:{(
xie
)}
b、可变集合
- (void)mutableSet
{
// 添加
NSArray *array = @[@"xie",@"jia",@"pei"];
NSMutableSet *set = [NSMutableSet setWithCapacity:10];
[set addObjectsFromArray:array];
NSSet *newSet = [NSSet setWithSet:set];
// 删除
[set removeObject:@"xie"];
NSLog(@"删除元素后,新set为:%@",set);
// 并集
[set unionSet:newSet];
NSLog(@"set取并集为:%@",set);
// 交集
[set intersectsSet:newSet];
NSLog(@"set取交集为:%@",set);
// 差集
[set minusSet:newSet];
NSLog(@"set取差集为:%@",set);
}
输出结果为:
2020-11-03 09:37:00.269452+0800 FoundationDemo[92558:3964819] 删除元素后,新set为:{(
jia,
pei
)}
2020-11-03 09:37:00.269550+0800 FoundationDemo[92558:3964819] set取并集为:{(
xie,
jia,
pei
)}
2020-11-03 09:37:00.269630+0800 FoundationDemo[92558:3964819] set取交集为:{(
xie,
jia,
pei
)}
2020-11-03 09:37:00.269690+0800 FoundationDemo[92558:3964819] set取差集为:{(
)}
c、带重复次数的集合
- (void)countedSet
{
NSCountedSet *set = [NSCountedSet setWithObjects:@"xie",@"jia", nil];
[set addObject:@"xie"];
[set addObject:@"pei"];
NSLog(@"带有重复次数的set为:%@",set);
NSLog(@"xie这个字符串出现的次数为:%lu",(unsigned long)[set countForObject:@"xie"]);
}
输出结果为:
2020-11-03 09:40:29.104474+0800 FoundationDemo[92640:3968983] 带有重复次数的set为:<NSCountedSet: 0x6000009692c0> (xie [2], jia [1], pei [1])
2020-11-03 09:40:29.104555+0800 FoundationDemo[92640:3968983] xie这个字符串出现的次数为:2
2、NSDictionary
a、创建字典并取值
- (void)createDictionary
{
PersonClass *person = [[PersonClass alloc] init];
// 通过语法糖创建字典
NSDictionary *dict = @{@"name": @"XieJiaPei", @"age": @22, @4: @5, person: @"FanYiCheng"};
NSLog(@"原始字典为:%@",dict);
// 从字典中取值
NSLog(@"字典中的姓名为:%@,年龄为:%@,倘若没有Key值为:%@",dict[@"name"],[dict objectForKey:@"age"],dict[@"noKey"]);
// 通过初始化方法创建字典
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: @"XieJiaPei",@"name",@22,@"age",person,@"FanYiCheng",nil];
NSLog(@"key-value对数量: %lu",(unsigned long)[dictionary count]);
NSLog(@"allKey: %@",[dictionary allKeys]);
NSLog(@"allValues: %@",[dictionary allValues]);
NSLog(@"key不同,值相同,这种情况的所有key为: %@",[dictionary allKeysForObject:@"XieJiaPei"]);
}
输出结果为:
2020-10-30 17:34:07.613893+0800 FoundationDemo[47518:1783828] 原始字典为:{
age = 22;
"<PersonClass: 0x600002828300>" = (null);
name = XieJiaPei;
4 = 5;
}
2020-10-30 17:34:07.613982+0800 FoundationDemo[47518:1783828] 字典中的姓名为:XieJiaPei,年龄为:22,倘若没有Key值为:(null)
2020-10-30 17:34:07.614057+0800 FoundationDemo[47518:1783828] key-value对数量: 3
2020-10-30 17:34:07.614140+0800 FoundationDemo[47518:1783828] allKey: (
name,
age,
FanYiCheng
)
2020-10-30 17:34:07.614212+0800 FoundationDemo[47518:1783828] allValues: (
XieJiaPei,
22,
"<PersonClass: 0x600002828980>"
)
2020-10-30 17:34:07.614295+0800 FoundationDemo[47518:1783828] key不同,值相同,这种情况的所有key为: (
name
)
b、遍历字典
- (void)enumerateDictionary
{
PersonClass *person = [[PersonClass alloc] init];
NSDictionary *dict = @{@"name": @"XieJiaPei", @"age": @22, @4: @5, person: @"FanYiCheng"};
// 使用指定代码块来迭代执行该集合中所有key-value对
[dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop)
{
NSLog(@"key的值为:%@,value的值:%@", key, obj);
}];
}
输出结果为:
2020-10-30 17:40:27.704477+0800 FoundationDemo[47616:1788769] key的值为:age,value的值:22
2020-10-30 17:40:27.704543+0800 FoundationDemo[47616:1788769] key的值为:<PersonClass: 0x600001435f80>,value的值:FanYiCheng
2020-10-30 17:40:27.704610+0800 FoundationDemo[47616:1788769] key的值为:name,value的值:XieJiaPei
2020-10-30 17:40:27.704690+0800 FoundationDemo[47616:1788769] key的值为:4,value的值:5
c、写入文件
- (void)dictionaryWriteToFile
{
// 我发现要写入plist文件,key必须为string类型
NSDictionary *dict = @{@"name": @"XieJiaPei", @"age": @22, @"4": @5};
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentPath stringByAppendingPathComponent:@"jia.plist"];
// 将路径转换为本地url形式
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
// writeToURL 的好处是,既可以写入本地url也可以写入远程url,苹果推荐使用此方法写入plist文件
if ( [dict writeToURL:fileUrl atomically:YES] )
{
NSLog(@"成功写入文件,路径为:%@",filePath);
}
NSDictionary *dictionaryFromFile = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"从文件中读取到的字典为:%@",dictionaryFromFile);
}
输出结果为:
2020-10-30 17:58:34.469548+0800 FoundationDemo[47972:1807344] 成功写入文件,路径为:/Users/xiejiapei/Library/Developer/CoreSimulator/Devices/4E4809CA-E567-4D3A-8ADE-790075200303/data/Containers/Data/Application/62175E05-6FFD-4EEF-A872-3C08B6FBACB4/Documents/jia.plist
2020-10-30 17:58:34.469723+0800 FoundationDemo[47972:1807344] 从文件中读取到的字典为:{
4 = 5;
age = 22;
name = XieJiaPei;
}
d、字典排序
- (void)compareDictionary
{
NSDictionary *numberDict = @{@"Xie": @22, @"Liu": @18, @"Zou": @19};
// compare:
NSArray *newKeys = [numberDict keysSortedByValueUsingSelector:@selector(compare:)];
NSLog(@"集合元素自身的排序方法(compare:),字典通过比较值将key排序后为:%@", newKeys);
// block:
NSDictionary *stringDict = @{@"Xie": @"apple", @"Liu": @"Banana", @"Zou": @"watermelon"};
newKeys = [stringDict keysSortedByValueUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2)
{
if ([obj1 length] > [obj2 length])
{
return NSOrderedDescending;
}
if ([obj1 length] < [obj2 length])
{
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSLog(@"通过代码块排序,定义比较大小的标准:字符串越长越大,排序后key为:%@", newKeys);
}
输出结果为:
2020-10-30 18:10:00.621205+0800 FoundationDemo[48152:1816838] 集合元素自身的排序方法(compare:),字典通过比较值将key排序后为:(
Liu,
Zou,
Xie
)
2020-10-30 18:10:00.621368+0800 FoundationDemo[48152:1816838] 通过代码块排序,定义比较大小的标准:字符串越长越大,排序后key为:(
Xie,
Liu,
Zou
)
e、字典过滤
- (void)filteredDictionary
{
NSDictionary *numberDict = @{@"Xie": @22, @"Liu": @18, @"Zou": @19};
NSSet *keySet = [numberDict keysOfEntriesPassingTest:^BOOL(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop)
{
return ([obj intValue] < 20);
}];
NSLog(@"真羡慕,你俩都好小呀:%@",keySet);
}
输出结果为:
2020-10-30 18:13:51.339440+0800 FoundationDemo[48212:1821809] 真羡慕,你俩都好小呀:{(
Liu,
Zou
)}
f、可变字典
- (void)mutableDictionary
{
NSDictionary *numberDict = @{@"Xie": @22, @"Liu": @18, @"Zou": @19};
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:numberDict];
mutableDict[@"Xie"] = @"love Liu";
NSLog(@"覆盖值后,字典为:%@",mutableDict);
mutableDict[@"marray"] = @"baby";
NSLog(@"添加新元素后,字典为:%@",mutableDict);
[mutableDict addEntriesFromDictionary:@{@"Lin":@21}];
NSLog(@"添加另外一个字典后,字典为:%@",mutableDict);
[mutableDict removeObjectForKey:@"Xie"];
NSLog(@"删除元素后,字典为:%@",mutableDict);
}
输出结果为:
2020-10-30 18:19:20.392259+0800 FoundationDemo[48302:1826112] 覆盖值后,字典为:{
Liu = 18;
Xie = "love Liu";
Zou = 19;
}
2020-10-30 18:19:20.392358+0800 FoundationDemo[48302:1826112] 添加新元素后,字典为:{
Liu = 18;
Xie = "love Liu";
Zou = 19;
marray = baby;
}
2020-10-30 18:19:20.392443+0800 FoundationDemo[48302:1826112] 添加另外一个字典后,字典为:{
Lin = 21;
Liu = 18;
Xie = "love Liu";
Zou = 19;
marray = baby;
}
2020-10-30 18:19:20.392513+0800 FoundationDemo[48302:1826112] 删除元素后,字典为:{
Lin = 21;
Liu = 18;
Zou = 19;
marray = baby;
}
3、NSArray
a、创建数组
NSArray *aArray = @[@1, @2, @3];
NSArray<NSString *> *bArray = @[@"2", @"4", @"3", @"1"];
NSArray *cArray = [NSArray arrayWithObjects:@1, @"XieJiaPei", person, nil];
NSArray *dArray = [NSArray arrayWithObjects:@1, @"XieJiaPei", nil, @5, person, nil];
NSLog(@"原始数组A为:%@",aArray);
NSLog(@"原始数组B为:%@",bArray);
NSLog(@"原始数组A为:%@",cArray);
NSLog(@"原始数组C为:%@",dArray);
输出结果为:
2020-10-21 16:48:29.731149+0800 BasicGrammarDemo[1505:46009] 原始数组A为:(
1,
2,
3
)
2020-10-21 16:48:29.731213+0800 BasicGrammarDemo[1505:46009] 原始数组B为:(
2,
4,
3,
1
)
2020-10-21 16:48:29.731286+0800 BasicGrammarDemo[1505:46009] 原始数组A为:(
1,
XieJiaPei,
"<PersonClass: 0x600002dfa140>"
)
2020-10-21 16:48:29.731345+0800 BasicGrammarDemo[1505:46009] 原始数组C为:(
1,
XieJiaPei
)
b、从数组中取值
NSString *index1IncArray = [cArray objectAtIndex:1];
NSNumber *index0IncArray = cArray[0];
NSLog(@"数组C中下标0的值为:%@,下标1的值为:%@",index0IncArray,index1IncArray);
NSArray *array = @[@"xie",@"jia",@"pei",@"fan",@"yi",@"cheng",@"lin",@"feng",@"mian"];
NSArray *newArray = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
NSLog(@"获取索引从2~5的元素组成的新集合:%@",newArray);
NSLog(@"获取元素在集合中的位置:%lu",(unsigned long)[array indexOfObject:@"xie"]);
array = [array arrayByAddingObjectsFromArray:newArray];
NSLog(@"向array数组的最后追加另一个数组的所有元素:%@",array);
array = [array subarrayWithRange:NSMakeRange(5, 3)];
NSLog(@"索引为5~8处的所有元素:%@",array);
输出结果为:
2020-10-21 16:48:29.765873+0800 BasicGrammarDemo[1505:46009] 数组C中下标0的值为:1,下标1的值为:XieJiaPei
2020-10-30 15:08:34.786959+0800 FoundationDemo[45297:1678179] 获取索引从2~5的元素组成的新集合:(
pei,
fan,
yi
)
2020-10-30 15:08:34.787054+0800 FoundationDemo[45297:1678179] 获取元素在集合中的位置:0
2020-10-30 15:08:34.787135+0800 FoundationDemo[45297:1678179] 向array数组的最后追加另一个数组的所有元素:(
xie,
jia,
pei,
fan,
yi,
cheng,
lin,
feng,
mian,
pei,
fan,
yi
)
2020-10-30 15:08:34.787201+0800 FoundationDemo[45297:1678179] 索引为5~8处的所有元素:(
cheng,
lin,
feng
)
c、给数组排序
NSArray *sortedArray = [bArray sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"集合元素自身的排序方法(compare:),数组B排序后为:%@", sortedArray);
NSArray *sortedArrayByFunction = [bArray sortedArrayUsingFunction:intSort context:nil];
NSLog(@"通过函数排序,数组B排序后为:%@", sortedArrayByFunction);
NSArray *sortedArrayByBlock = [bArray sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2)
{
if ([obj1 integerValue] > [obj2 integerValue])
{
return NSOrderedDescending;
}
if ([obj1 intValue] < [obj2 intValue])
{
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSLog(@"通过代码块排序,数组B排序后为:%@", sortedArrayByBlock);
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
输出结果为:
2020-10-30 15:19:30.831961+0800 FoundationDemo[45456:1686606] 集合元素自身的排序方法(compare:),数组B排序后为:(
1,
2,
3,
4
)
2020-10-30 15:19:30.832052+0800 FoundationDemo[45456:1686606] 通过函数排序,数组B排序后为:(
1,
2,
3,
4
)
2020-10-30 15:19:30.832179+0800 FoundationDemo[45456:1686606] 通过代码块排序,数组B排序后为:(
1,
2,
3,
4
)
d、让数组过滤数据
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF matches %@", @"[3-9]+"];
NSArray *filteredArray = [bArray filteredArrayUsingPredicate:predicate];
NSLog(@"数组B过滤数据(只留下3-9之间的数据)后为:%@", filteredArray);
输出结果为:
2020-10-21 16:53:27.058488+0800 BasicGrammarDemo[1615:51718] 数组B过滤数据(只留下3-9之间的数据)后为:(
4,
3
)
e、可变数组
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:@[@"xie",@"jia",@"pei",@"fan",@"yi",@"cheng"]];
// 向集合最后添加一个元素
[mutableArray addObject:@"liu"];
// 向集合尾部添加多个元素
[mutableArray addObjectsFromArray:@[@"ying",@"chi"]];
NSLog(@"向集合最后位置添加元素后数组为:%@",mutableArray);
// 指定位置插入一个元素
[mutableArray insertObject:@"GuanYu" atIndex:1];
// 指定位置插入多个元素
[mutableArray insertObjects:@[@"ZhangFei",@"ZhaoYun"] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];
NSLog(@"指定位置插入元素后数组为:%@",mutableArray);
// 删除最后一个元素
[mutableArray removeLastObject];
// 删除指定索引处的元素
[mutableArray removeObjectAtIndex:5];
// 删除2~5处元素
[mutableArray removeObjectsInRange:NSMakeRange(2, 3)];
NSLog(@"删除元素后数组为:%@",mutableArray);
// 替换索引为2处的元素
[mutableArray replaceObjectAtIndex:2 withObject:@"MaChao"];
NSLog(@"替换可变数组中的数据后为:%@",mutableArray);
输出结果为:
2020-10-30 17:00:55.532047+0800 FoundationDemo[46981:1758054] 向集合最后位置添加元素后数组为:(
xie,
jia,
pei,
liu,
ying,
chi
)
2020-10-30 17:00:55.532186+0800 FoundationDemo[46981:1758054] 指定位置插入元素后数组为:(
xie,
ZhangFei,
ZhaoYun,
GuanYu,
jia,
pei,
liu,
ying,
chi
)
2020-10-30 17:00:55.532264+0800 FoundationDemo[46981:1758054] 删除元素后数组为:(
xie,
ZhangFei,
liu,
ying
)
2020-10-30 17:00:55.532336+0800 FoundationDemo[46981:1758054] 替换可变数组中的数据后为:(
xie,
ZhangFei,
MaChao,
ying
)
f、数组的拷贝
NSArray *shallowCopyArray = [bArray copy];
NSLog(@"原数组为不可变数组——使用copy——结果数组为不可变数组,比较是否相等的结果为:%@", shallowCopyArray == bArray ? @"相等" : @"不相等");
NSLog(@"原数组为不可变数组——使用copy——结果数组为不可变数组,比较元素是否相等的结果为:%@", shallowCopyArray[3] == bArray[3] ? @"相等" : @"不相等");
NSMutableArray *mutableCopyArray = [bArray mutableCopy];
NSLog(@"原数组为不可变数组——使用mutableCopy——结果数组为可变数组,比较是否相等的结果为:%@", mutableCopyArray == bArray ? @"相等" : @"不相等");
NSMutableArray *copyArray = [mutableCopyArray copy];
NSLog(@"原数组为可变数组——使用copy——结果数组为可变数组,比较是否相等的结果为:%@", copyArray == mutableCopyArray ? @"相等" : @"不相等");
NSMutableArray *anotherMutableCopyArray = [mutableCopyArray mutableCopy];
NSLog(@"原数组为可变数组——使用mutableCopy——结果数组为可变数组,比较是否相等的结果为:%@", anotherMutableCopyArray == mutableCopyArray ? @"相等" : @"不相等");
输出结果为:
2020-10-21 17:16:15.239156+0800 BasicGrammarDemo[2026:73856] 原数组为不可变数组——使用copy——结果数组为不可变数组,比较是否相等的结果为:相等
2020-10-21 17:16:15.239212+0800 BasicGrammarDemo[2026:73856] 原数组为不可变数组——使用copy——结果数组为不可变数组,比较元素是否相等的结果为:相等
2020-10-21 17:16:15.239280+0800 BasicGrammarDemo[2026:73856] 原数组为不可变数组——使用mutableCopy——结果数组为可变数组,比较是否相等的结果为:不相等
2020-10-21 17:16:15.239336+0800 BasicGrammarDemo[2026:73856] 原数组为可变数组——使用copy——结果数组为可变数组,比较是否相等的结果为:不相等
2020-10-21 17:16:15.239401+0800 BasicGrammarDemo[2026:73856] 原数组为可变数组——使用mutableCopy——结果数组为可变数组,比较是否相等的结果为:不相等
g、数组的遍历
一般的遍历方式包括for循环
、NSEnumerator
、for in
。比较特殊的遍历方式enumerateObjectsUsingBlock
是通过block
回调,在子线程中遍历,对象的回调次序是乱序的,而且调用线程会等待该遍历过程完成。这几个遍历方式中for in
性能最好,for循环
较低, 多线程遍历方式是性能最差的。
for (NSString *string in bArray)
{
NSLog(@"使用快速遍历,字符串为:%@",string);
}
NSEnumerator *enumerator = [bArray objectEnumerator];
id object;
while (object = [enumerator nextObject])
{
NSLog(@"使用顺序枚举器,数值为:%@",object);
}
NSEnumerator *reverseEnumerator = [bArray reverseObjectEnumerator];
while (object = [reverseEnumerator nextObject])
{
NSLog(@"使用逆序枚举器,数值为:%@" , object);
}
输出结果为:
2020-10-30 15:26:21.535811+0800 FoundationDemo[45562:1691741] 使用快速遍历,字符串为:2
2020-10-30 15:26:21.535861+0800 FoundationDemo[45562:1691741] 使用快速遍历,字符串为:4
2020-10-30 15:26:21.535928+0800 FoundationDemo[45562:1691741] 使用快速遍历,字符串为:3
2020-10-30 15:26:21.535992+0800 FoundationDemo[45562:1691741] 使用快速遍历,字符串为:1
2020-10-30 15:26:21.536155+0800 FoundationDemo[45562:1691741] 使用顺序枚举器,数值为:2
2020-10-30 15:26:21.536255+0800 FoundationDemo[45562:1691741] 使用顺序枚举器,数值为:4
2020-10-30 15:26:21.536402+0800 FoundationDemo[45562:1691741] 使用顺序枚举器,数值为:3
2020-10-30 15:26:21.536514+0800 FoundationDemo[45562:1691741] 使用顺序枚举器,数值为:1
2020-10-30 15:26:21.536622+0800 FoundationDemo[45562:1691741] 使用逆序枚举器,数值为:1
2020-10-30 15:26:21.536748+0800 FoundationDemo[45562:1691741] 使用逆序枚举器,数值为:3
2020-10-30 15:26:21.536884+0800 FoundationDemo[45562:1691741] 使用逆序枚举器,数值为:4
2020-10-30 15:26:21.536991+0800 FoundationDemo[45562:1691741] 使用逆序枚举器,数值为:2
h、写入文件
NSArray<NSString *> *bArray = @[@"2", @"4", @"3", @"1"];
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentPath stringByAppendingFormat:@"/%@",@"xie.plist"];
if ( [bArray writeToFile:filePath atomically:YES] )
{
NSLog(@"成功写入文件,路径为:%@",filePath);
}
NSArray *arrayFromFile = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"从文件中读取到的数组为:%@",arrayFromFile);
输出结果为:
2020-10-30 16:40:54.419610+0800 FoundationDemo[46618:1741321] 成功写入文件,路径为:/Users/xiejiapei/Library/Developer/CoreSimulator/Devices/4E4809CA-E567-4D3A-8ADE-790075200303/data/Containers/Data/Application/27126598-B9C0-4156-BC10-D3EAC6697F7F/Documents/xie.plist
2020-10-30 16:40:54.419790+0800 FoundationDemo[46618:1741321] 从文件中读取到的数组为:(
2,
4,
3,
1
)
I、整体调用方法
- (void)performSelector
{
PersonClass *person = [[PersonClass alloc] init];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:@[person,person,person,person]];
// 对集合元素整体调用方法
[mutableArray makeObjectsPerformSelector:@selector(printPetPhrase:) withObject:@"锤子"];
NSLog(@"对集合元素整体调用方法:%@",mutableArray);
// 迭代集合内指定范围内元素,并使用该元素来执行代码块
[mutableArray enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)] options:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"正在处理第%ld个元素:%@" , idx , obj);
}];
}
- (void)printPetPhrase:(NSString *)petPhrase
{
NSLog(@"你的口头禅是什么呀?%@",petPhrase);
}
输出结果为:
2020-10-30 17:22:03.303271+0800 FoundationDemo[47347:1775321] 你的口头禅是什么呀?锤子
2020-10-30 17:22:03.303360+0800 FoundationDemo[47347:1775321] 你的口头禅是什么呀?锤子
2020-10-30 17:22:03.303433+0800 FoundationDemo[47347:1775321] 你的口头禅是什么呀?锤子
2020-10-30 17:22:03.303490+0800 FoundationDemo[47347:1775321] 你的口头禅是什么呀?锤子
2020-10-30 17:22:03.303692+0800 FoundationDemo[47347:1775321] 正在处理第2个元素:<PersonClass: 0x6000031ac880>
2020-10-30 17:22:03.303758+0800 FoundationDemo[47347:1775321] 正在处理第1个元素:<PersonClass: 0x6000031ac880>
J、数组去除重复元素
利用NSSet
特性, 放入集合自动去重。这种方法更快,利用NSSet
不会添加重复元素的特性。
NSArray *selected = [deleteDuplicateSet allObjects];
不过去重的数组没有进行排序,如果需要排序,可以使用NSSortDescriptor
类。
NSSet *deleteDuplicateSet = [NSSet setWithArray:self.switchAlbumSelectList];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
NSArray *selected = [deleteDuplicateSet sortedArrayUsingDescriptors:sortDescriptors];
利用NSDictionary
的AllKeys
(AllValues
)方法可以将NSArray
中的元素存入一个字典,然后利用AllKeys
或者AllValues
取得字典的所有键或值,这些键或值都是去重的。结果为无序的,也就是说不包含原有顺序,可自行加入排序算法。
NSArray *originalArr = @[@1, @2, @3, @1, @3];
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
for (NSNumber *n in originalArr) {
[dict setObject:n forKey:n];
}
NSLog(@"%@",[dictM allValues]);
通过valueForKeyPath
去重只需一行代码。
NSArray *originalArr = @[@1, @2, @3, @1, @3];
NSArray *result = [originalArr valueForKeyPath:@"@distinctUnionOfObjects.self"];
开辟新的内存空间,判断是否存在,若不存在则添加到数组中,得到最终结果的顺序不发生变化。
// 只能通过这种方式去重,而不能使用字典、Set,因为要保证批量上传的顺序按照选择时候的顺序
NSMutableArray *selected = [NSMutableArray array];
for (UCARPhotoModel *photo in self.switchAlbumSelectList)
{
if (![selected containsObject:photo])
{
[selected addObject:photo];
}
}
六、NSDate
1、Date
a、创建日期
- (void)date
{
// 使用时间间隔创建日期
NSTimeInterval secondsPerDay = 24 * 60 * 60;// 一天
NSDate *tomorrow1 = [[NSDate alloc] initWithTimeIntervalSinceNow:secondsPerDay];// 明天
NSDate *yesterday1 = [[NSDate alloc] initWithTimeIntervalSinceNow:-secondsPerDay];// 昨天
NSLog(@"使用时间间隔创建日期,昨天:%@,明天:%@",yesterday1, tomorrow1);
// 通过添加时间间隔创建日期
NSDate *today = [NSDate date];
NSDate *tomorrow2 = [today dateByAddingTimeInterval:secondsPerDay];// 明天
NSDate *yesterday2 = [today dateByAddingTimeInterval:-secondsPerDay];// 昨天
NSLog(@"使用时间间隔创建日期,昨天:%@,明天:%@",yesterday2, tomorrow2);
// 从1970年1月1日开始,20年之后的日期
NSDate *twentyYearsDate = [NSDate dateWithTimeIntervalSince1970:secondsPerDay*366*20];
NSLog(@"从1970年1月1日开始,20年之后的日期:%@",twentyYearsDate);
}
输出结果为:
2020-09-24 11:05:35.266263+0800 BasicGrammarDemo[97687:17759303] 使用时间间隔创建日期,昨天:2020-09-23 03:05:35 +0000,明天:2020-09-25 03:05:35 +0000
2020-09-24 11:05:35.266383+0800 BasicGrammarDemo[97687:17759303] 通过添加时间间隔创建日期,昨天:2020-09-23 03:05:35 +0000,明天:2020-09-25 03:05:35 +0000
2020-09-24 11:32:29.711559+0800 BasicGrammarDemo[98039:17779918] 从1970年1月1日开始,20年之后的日期:1990-01-16 00:00:00 +0000
b、比较日期
可以使用isEqualToDate:
、compare:
、laterDate:
、earlierDate:
方法。
- (void)compareDate
{
NSDate *today = [NSDate date];// 今天
NSDate *tomorrow = [today dateByAddingTimeInterval:24 * 60 * 60];// 明天
// 看看两个日期是否在一分钟(60秒)内
// fabs:求一个实数的绝对值
if (fabs([tomorrow timeIntervalSinceDate:today]) < 60)
{
NSLog(@"两个日期在一分钟(60秒)内");
}
else
{
NSLog(@"两个日期不在一分钟(60秒)内");
}
// 之前、相同、之后
switch ([today compare:tomorrow])
{
case NSOrderedAscending:
NSLog(@"之前");
break;
case NSOrderedSame:
NSLog(@"相等");
break;
case NSOrderedDescending:
NSLog(@"之后");
break;
}
// 返回比较的两个日期中更早的那个
today = [today earlierDate:tomorrow];
NSLog(@"较早的日期:%@",today);
// 返回比较的两个日期中更晚的那个
today = [today laterDate:tomorrow];
NSLog(@"较晚的日期:%@",today);
}
输出结果为:
2020-09-24 14:40:57.125611+0800 BasicGrammarDemo[99895:17885247] 两个日期不在一分钟(60秒)内
2020-09-24 14:40:57.125685+0800 BasicGrammarDemo[99895:17885247] 之前
2020-09-24 14:40:57.125769+0800 BasicGrammarDemo[99895:17885247] 较早的日期:2020-09-24 06:40:57 +0000
2020-09-24 14:40:57.125844+0800 BasicGrammarDemo[99895:17885247] 较晚的日期:2020-09-25 06:40:57 +0000
c、日期格式
// 日期格式
- (void)dateFormat
{
// 时间的本地化
NSDate *today = [NSDate date];
NSLocale *locale = [NSLocale currentLocale];// 系统当前的Locale
[today descriptionWithLocale:locale];
NSLog(@"时间的本地化:%@",today);
// 创建两个NSLocale,分别代表中国、美国
NSLocale *locales[] = {[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"], [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]};
// 设置NSDateFormatter的日期、时间风格
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
// NSLocale
[dateFormatter setLocale:locales[0]];
// 设置自定义的格式模板
[dateFormatter setDateFormat:@"公元yyyy年MM月DD日 HH时mm分"];
// stringFromDate
NSString* stringFromDate = [dateFormatter stringFromDate:today];
NSLog(@"stringFromDate 时间的格式化:%@",stringFromDate);
// dateFromString
NSString *dateString = @"2020-01-18 06:50:24";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *dateFromString = [formatter dateFromString:dateString];
NSLog(@"dateFromString 时间的格式化:%@",dateFromString);
}
输出结果为:
2020-09-24 14:55:48.071631+0800 BasicGrammarDemo[309:17900007] 时间的本地化:2020-09-24 06:55:48 +0000
2020-09-24 14:55:48.072018+0800 BasicGrammarDemo[309:17900007] stringFromDate 时间的格式化:公元2020年09月268日 14时55分
2020-09-24 15:11:59.105726+0800 BasicGrammarDemo[764:17914033] dateFromString 时间的格式化:2020-01-17 22:50:24 +0000
d、时间戳
- (void)dateInterval
{
NSDate *today = [NSDate date];// 今天
NSDate *tomorrow = [today dateByAddingTimeInterval:24 * 60 * 60];// 明天
// 时间差
double interval = [today timeIntervalSinceDate:tomorrow];
NSLog(@"与明天的时间差:%f",interval);
// 与现在的时间差
interval = [today timeIntervalSinceNow];
NSLog(@"与现在的时间差:%f",interval);
}
输出结果为:
2020-09-24 14:40:57.126282+0800 BasicGrammarDemo[99895:17885247] 与明天的时间差:-86400.000000
2020-09-24 14:40:57.126339+0800 BasicGrammarDemo[99895:17885247] 与现在的时间差:-0.000070
2、Calendar
a、创建日历
- (void)calendar
{
// 创建日历对象
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
// local、usersCalendar和currentCalendar是相等的,尽管它们是不同的对象
NSCalendar *usersCalendar = [[NSLocale currentLocale] objectForKey:NSLocaleCalendar];
// 还可以通过为所需日历指定标识符来创建任意日历对象
// 获取代表公历的Calendar对象
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
}
b、通过日历获取不同时间字段的信息
- (void)calendar
{
NSDate *date = [NSDate date];
NSLog(@"现在日期为:%@",date);
// 还可以通过为所需日历指定标识符来创建任意日历对象
// 获取代表公历的Calendar对象
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// 定义一个时间字段的旗标,指定将会获取指定年、月、日、时、分、秒的信息
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitWeekday;
// 获取不同时间字段的信息
NSDateComponents *components = [gregorian components:unitFlags fromDate:date];
NSLog(@"年:%ld 月:%ld ",(long)components.year,(long)components.month);
}
输出结果为:
2020-09-24 11:17:01.315888+0800 BasicGrammarDemo[97860:17769221] 现在日期为:2020-09-24 03:17:01 +0000
2020-09-24 11:17:01.316009+0800 BasicGrammarDemo[97860:17769221] 年:2020 月:9
c、通过日历设置各时间字段的数值
// 设置各时间字段的数值
NSDateComponents *newComponents = [[NSDateComponents alloc] init];
newComponents.year = 2020;
newComponents.month = 10;
newComponents.day = 1;
// 恢复NSDate
date = [gregorian dateFromComponents:newComponents];
NSLog(@"设置的日期为:%@",date);
输出结果为:
2020-09-24 11:17:01.316112+0800 BasicGrammarDemo[97860:17769221] 设置的日期为:2020-10-17 16:00:00 +0000
d、日期组件
- (void)dateComponents
{
// 从日期获取组件
NSDate *today = [NSDate date];
// 获取代表公历的Calendar对象
NSCalendar *decompose = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// 指定将会获取指定周、日的信息
NSDateComponents *weekdayComponents = [decompose components:(NSCalendarUnitDay | NSCalendarUnitWeekday) fromDate:today];
NSInteger day = [weekdayComponents day];
NSInteger newWeekday = [weekdayComponents weekday];
NSLog(@"今天是:%@",today);
NSLog(@"从日期获取组件 day:%ld, newWeekday:%ld",(long)day,(long)newWeekday);
// 从组件创建日期
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:2];// 星期一
[components setWeekdayOrdinal:1];// 这个月的第一个星期一
[components setMonth:10];
[components setYear:2020];
NSDate *getDate = [decompose dateFromComponents:components];
NSLog(@"从组件创建日期:%@",getDate);
}
输出结果为:
2020-09-24 15:09:33.838392+0800 BasicGrammarDemo[724:17912053] 今天是:2020-09-24 07:09:33 +0000
2020-09-24 15:09:33.838503+0800 BasicGrammarDemo[724:17912053] 从日期获取组件 day:24, newWeekday:5
2020-09-24 15:09:33.838631+0800 BasicGrammarDemo[724:17912053] 从组件创建日期:2020-10-01 16:00:00 +0000
e、计算日期
- (void)calculateDate
{
NSDate *today = [[NSDate alloc] init];
NSDate *tomorrow = [[NSDate alloc] initWithTimeIntervalSinceNow:24 * 60 * 60];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// 增加一个半小时后
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setHour:1];
[offsetComponents setMinute:30];
NSDate *endOfWorldWar3 = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
NSLog(@"现在的时间是:%@",today);
NSLog(@"一个半小时后就是第三次世界大战的结束时间:%@",endOfWorldWar3);
// 通过减去日期来获取前一周的星期天 9月24日为周四,则上周日为9月20日,具有与原始日期相同的小时、分钟和秒
NSDateComponents *weekdayComponents = [gregorian components:NSCalendarUnitWeekday fromDate:today];
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
// 从当前日期减去的天数,公历中星期日的值是1,所以减去1,如果今天是星期日,则减去0天
[componentsToSubtract setDay:(0 - ([weekdayComponents weekday] - 1))];
NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:today options:0];
NSLog(@"通过减去日期来获取前一周的星期天:%@",beginningOfWeek);
// 获取两个日期之间的差异
NSUInteger unitFlags = NSCalendarUnitDay | NSCalendarUnitMonth;
NSDateComponents *components = [gregorian components:unitFlags fromDate:today toDate:tomorrow options:0];
NSInteger months = [components month];
// 输出两个日期day差数为0,因为8.5小时不到1天
NSInteger days = [components day];
NSLog(@"获取两个日期之间的差异,days:%ld,months:%ld",(long)days,(long)months);
}
输出结果为:
2020-09-24 15:27:18.050866+0800 BasicGrammarDemo[1024:17927076] 现在的时间是:2020-09-24 07:27:18 +0000
2020-09-24 15:27:18.050986+0800 BasicGrammarDemo[1024:17927076] 一个半小时后就是第三次世界大战的结束时间:2020-09-24 08:57:18 +0000
2020-09-24 15:27:18.051097+0800 BasicGrammarDemo[1024:17927076] 通过减去日期来获取前一周的星期天:2020-09-20 07:27:18 +0000
2020-09-24 15:27:18.051178+0800 BasicGrammarDemo[1024:17927076] 获取两个日期之间的差异,days:1,months:0
七、NSTimer
1、不重复的timer
// 在默认模式(NSDefaultRunLoopMode)下,用当前NSRunLoop对象自动注册新计时器
- (void)startTimer
{
// 计时器在2秒后由运行循环自动触发,然后从运行循环中删除
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(targetMethod:) userInfo:self.userInfo repeats:NO];
}
- (void)targetMethod:(NSTimer *)theTimer
{
NSDate *startDate = [[theTimer userInfo] objectForKey:@"StartDate"];
NSLog(@"开始日期:%@",startDate);
}
- (NSDictionary *)userInfo
{
return @{@"StartDate": [NSDate date]};
}
如果创建非重复计时器,它会自动停止。输出结果为:
2020-09-24 10:31:01.237970+0800 BasicGrammarDemo[97131:17724123] 开始日期:2020-09-24 02:30:59 +0000
2、重复的timer
- (void)startRepeatingTimer
{
// 取消之前存在的timer
[_repeatingTimer invalidate];
// 创建新的timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(targetMethod:) userInfo:self.userInfo repeats:YES];
_repeatingTimer = timer;
}
如果创建重复计时器,将计数器的repeats
设置为YES
的时候,self
的引用计数会加1,因此可能会导致self
(即viewController
)不能释放,所以必须在viewDidDisappear
方法里将计数器timer
停止,否则可能会导致内存泄露,停止后,一定要将timer
赋空,否则还是没有释放,会造成不必要的内存开销。
- (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"退出了当前页面,销毁了定时器");
[self stopRepeatingTimer];
}
- (void)stopRepeatingTimer
{
// 将计数器timer停止,否则可能会导致内存泄露
[self.repeatingTimer invalidate];
// 停止后,一定要将timer赋空,否则还是没有释放,会造成不必要的内存开销
self.repeatingTimer = nil;
}
当再次进入定时器页面,重新开启定时器。
- (void)viewWillAppear:(BOOL)animated
{
NSLog(@"进入定时器页面,重新开启定时器");
// 开启定时器
[self.repeatingTimer setFireDate:[NSDate distantPast]];//很远的过去
}
输出结果为:
2020-09-24 10:39:10.396329+0800 BasicGrammarDemo[97268:17732297] 开始日期:2020-09-24 02:39:06 +0000
2020-09-24 10:39:10.896330+0800 BasicGrammarDemo[97268:17732297] 开始日期:2020-09-24 02:39:06 +0000
2020-09-24 10:39:11.243983+0800 BasicGrammarDemo[97268:17732297] 退出了当前页面,销毁了定时器
2020-09-24 10:39:13.011582+0800 BasicGrammarDemo[97268:17732297] 进入定时器页面,重新开启定时器
发现定时器被销毁了,无法重新开启,所以可以使用viewWillDisappear
替代viewDidDisappear
里的实现。
// 在页面消失的时候关闭定时器,然后等页面再次打开的时候,又开启定时器
- (void)viewWillDisappear:(BOOL)animated
{
// 关闭定时器
[self.repeatingTimer setFireDate:[NSDate distantFuture]]; //很远的将来
NSLog(@"退出了当前页面,只是关闭定时器未销毁,再次进入可重新启动");
}
输出结果为:
2020-09-24 10:41:46.070295+0800 BasicGrammarDemo[97329:17735552] 开始日期:2020-09-24 02:41:44 +0000
2020-09-24 10:41:46.570290+0800 BasicGrammarDemo[97329:17735552] 开始日期:2020-09-24 02:41:44 +0000
2020-09-24 10:41:46.879144+0800 BasicGrammarDemo[97329:17735552] 退出了当前页面,只是关闭定时器未销毁,再次进入可重新启动
2020-09-24 10:41:48.834727+0800 BasicGrammarDemo[97329:17735552] 进入定时器页面,重新开启定时器
2020-09-24 10:41:48.837701+0800 BasicGrammarDemo[97329:17735552] 开始日期:2020-09-24 02:41:44 +0000
3、Invocation + RunLoop
只使用invocation
创建计时器。
- (void)createUnregisteredTimer
{
// 1、根据方法来初始化NSMethodSignature
// 方法签名中保存了方法的名称/参数/返回值,协同NSInvocation来进行消息的转发
NSMethodSignature *methodSignature = [self methodSignatureForSelector:@selector(invocationMethod:)];
// 2、其实NSInvocation就是将一个方法变成一个对象
// NSInvocation中保存了方法所属的对象/方法名称/参数/返回值
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
// 设置方法调用者
[invocation setTarget:self];
// 设置方法名称,这里的方法名一定要与方法签名类中的方法一致
[invocation setSelector:@selector(invocationMethod:)];
NSDate *startDate = [NSDate date];
// 设置方法参数,这里的Index要从2开始,因为0跟1已经被占据了,分别是self(target),selector
[invocation setArgument:&startDate atIndex:2];
// 3、调用invoke方法
[invocation invoke];
// 使用invocation创建计时器
NSTimer *timer = [NSTimer timerWithTimeInterval:0.5 invocation:invocation repeats:YES];
self.unregisteredTimer = timer;
//[self addTimerToRunLoop];// 未添加到runloop中时
}
- (void)invocationMethod:(NSDate *)date
{
NSLog(@"调用日期为:%@", date);
}
输出结果显示尽管计时器被配置为重复,但在触发一次之后,即被停止。
2020-09-24 10:45:21.267890+0800 BasicGrammarDemo[97383:17739828] 调用日期为:2020-09-24 02:45:21 +0000
现在将timer
添加到run loop
中。当前线程是主线程时,某些UI事件,比如ScrollView
正在拖动,将会RunLoop
切换成 NSEventTrackingRunLoopMode
模式,添加到RunLoop
中的Timer
就不会执行。
为了设置一个不被UI干扰的Timer
,我们需要手动创建一个Timer
,然后使用RunLoop
的 addTimer:forMode:
方法来把Timer
按照指定的模式加入到RunLoop
中。
这里使用 NSRunLoopCommonModes
模式,这个模式相当于 NSDefaultRunLoopMode
和 NSEventTrackingRunLoopMode
的结合。
// 将timer添加到run loop中
- (void)addTimerToRunLoop
{
if (self.unregisteredTimer != nil)
{
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.unregisteredTimer forMode:NSDefaultRunLoopMode];
}
}
打开[self addTimerToRunLoop]
语句的注释,输出结果为:
2020-09-24 10:49:05.506717+0800 BasicGrammarDemo[97429:17743337] 调用日期为:2020-09-24 02:49:04 +0000
2020-09-24 10:49:06.006756+0800 BasicGrammarDemo[97429:17743337] 调用日期为:2020-09-24 02:49:04 +0000
2020-09-24 10:49:06.506797+0800 BasicGrammarDemo[97429:17743337] 调用日期为:2020-09-24 02:49:04 +0000
.......
4、Fire Date + RunLoop
- (void)startFireDateTimer
{
// 用日期初始化计时器
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1.0];
// 尽管计时器被配置为重复,但在countedTimerFireMethod触发三次之后,它将停止
NSTimer *timer = [[NSTimer alloc] initWithFireDate:fireDate interval:0.5 target:self selector:@selector(countedTimerFireMethod:) userInfo:self.userInfo repeats:YES];
self.timerCount = 1;
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
}
// 给计时器计算调用次数
- (void)countedTimerFireMethod:(NSTimer *)theTimer
{
NSDate *startDate = [[theTimer userInfo] objectForKey:@"StartDate"];
NSLog(@"开始日期: %@,调用次数: %lu", startDate, (unsigned long)self.timerCount);
// 这将使计时器在触发三次后失效
self.timerCount++;
if (self.timerCount > 3)
{
[theTimer invalidate];
}
}
输出结果为:
2020-09-24 10:50:43.824386+0800 BasicGrammarDemo[97467:17746749] 开始日期: 2020-09-24 02:50:42 +0000,调用次数: 1
2020-09-24 10:50:44.323420+0800 BasicGrammarDemo[97467:17746749] 开始日期: 2020-09-24 02:50:42 +0000,调用次数: 2
2020-09-24 10:50:44.823579+0800 BasicGrammarDemo[97467:17746749] 开始日期: 2020-09-24 02:50:42 +0000,调用次数: 3
八、NSPredicate
1、谓词语法
下面方法都是区分大小写的,如果要不区分大小写,则可以在运算符后面使用[c]
。
AND、&&:逻辑与
OR || 逻辑或
NOT ! 逻辑非
字符串比较运算符:
BEGINSWITH 检查某个字符串是否以指定的某个子串开头
ENDSWITH 检查某个字符串是否以指定的某个子串结尾
CONTAINS 检查某个字符串是否包含指定的某个子串
LIKE 检查某个字符串是否匹配指定的字符串模板
MATCHES 检查某个字符串是否匹配指定的正则表达式
操作集合的运算符:
ANY SOME 指定只要集合中任意一个元素满足条件,即可返回YES。
ALL 指定所有元素满足才返回YES。
NONE 指定没有任何元素满足条件才返回YES。
IN 只有当左边的表达式或值出现在右边的集合中才会返回YES。
数组:
array[index] 返回array数组中索引为index处的元素
array[FIRST] 返回array数组中第一个元素
array[LAST] 返回array数组中最后一个元素
array[SIZE] 返回array数组中元素的个数。
直接量:
FALSE NO 逻辑假
TRUE YES 逻辑真
NULL NIL 代表一个空值
SELF 代表正在被判断的对象
"text"或'text' 代表字符串
数组 数组元素用英文字符隔开。eg:{'keli','zhangsan','lisi','wangwu'}
数值直接量 包括整数、小数、科学计数法
2、正则表达式语法
^ 指出一个字符串的开始
$ 指出一个字符串的结束
"^iOS" 以iOS开头
"iOS$" 以iOS结尾
"^apple$" 开始和结尾都是apple的字符串,这个是唯一的,实际上就是apple
"apple" 包含apple
* + ? 重复出现的次数
? 0~1次
+ 1~n次
* 0~n次
"ab*" 一个a后面跟着0~n个b
"ab+" 一个a后面跟着至少一个b
"ab?" 一个a后面跟着0~1个b
"a?b+$" 末尾有0~1个a跟着1~n个b
{} 表示重复的具体范围
"ab{4}" 一个a跟着4个b
"ab{1,}" 一个a跟着至少1个b
"ab{3,5}" 一个a跟着3~5个b
* 可以用{0,}表示
+ 可以用{1,}表示
? 可以用{0,1}表示
| 或
"a|b" 一个字符串里有a或b
"(a|bcd)ef" aef或bcdef
"(a|b)+c" 一串a和b混合的字符串后面跟一个c;
[ ] 表示在括号内的众多字符中,选择1-n个括号内的符合语法的字符作为结果
"[ab]" 一个a或b(相当于"a|b");
"[a-d]" a到d中的一个(相当于"a|b|c|d"或者"[abcd]")
"^[a-zA-Z]" 以字母开头
"[0-9]a" a前有一位数字
"[a-zA-Z0-9]$"以一个字母或数字结束
. 任意字符
"a.[a-z]" a后面跟一个任意字符和一个小写字母
"^.{5}$" 长度为5的字符串
"@[^a-zA-Z]@" 在方括号里用^表示不希望出现的字符,^应在方括号里的第一位。表示两个@中不应该出现字母
"\d" 一个数字字符
"\D" 一个非数字字符
"\w " 包括下划线的任何单词字符
"\W" 匹配任何非单词字符
\ iOS中书写正则表达式,碰到转义字符,多加一个\
3、包含关系
a、是否在数组之中
- (void)inArrayDemo
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@",@[@"先生女士",@"妙不可言",@"哈哈哈哈哈"]];
BOOL result = [predicate evaluateWithObject:@"哈哈哈哈哈"];
if (result)
{
NSLog(@"哈哈哈哈哈在数组中");
}
}
输出结果为:
2020-09-24 16:59:50.674351+0800 ChecksumsWarning[2412:18002210] 哈哈哈哈哈在数组中
b、字符匹配
- (void)characterMatch
{
NSString *prefix = @"prefix";
NSString *suffix = @"suffix";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF like[c] %@",[[prefix stringByAppendingString:@"*"] stringByAppendingString:suffix]];
NSLog(@"predicate = %@", [predicate predicateFormat]);
BOOL result = [predicate evaluateWithObject:@"prefixxxxxxsuffix"];
if (result)
{
NSLog(@"字符匹配成功");
}
else
{
NSLog(@"字符匹配失败");
}
}
输出结果为:
2020-09-24 17:23:59.032000+0800 ChecksumsWarning[2770:18022215] predicate = SELF LIKE[c] "prefix*suffix"
2020-09-24 17:23:59.033539+0800 ChecksumsWarning[2770:18022215] 字符匹配成功
4、数据过滤
a、比较大小
- (void)greaterThanDemo
{
NSArray* array = @[@101,@200,@50,@5,@25,@12];
NSLog(@"原数组:%@",array);
// 创建谓词,要求该对象自身的值大于50
NSPredicate *predicateThan50 = [NSPredicate predicateWithFormat:@"SELF > 50"];
// 使用谓词执行过滤,过滤后只剩下值大于50的集合元素
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicateThan50];
NSLog(@"数组过滤后只剩下值大于50的集合元素:%@",filteredArray);
}
输出结果为:
2020-09-24 16:18:24.591968+0800 ChecksumsWarning[1783:17966853] 原数组:(
101,
200,
50,
5,
25,
12
)
2020-09-24 16:18:24.592186+0800 ChecksumsWarning[1783:17966853] 数组过滤后只剩下值大于50的集合元素:(
101,
200
)
b、以特定字符开始
- (void)beginswithLetterDemo
{
// 过滤掉不是以b开始的字符串
NSMutableArray *letters = [@[@"Abc",@"Bbb",@"Ca"] mutableCopy];
NSPredicate *predictForArray = [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB = [letters filteredArrayUsingPredicate:predictForArray];
NSLog(@"过滤掉不是以b开始的字符串:%@",beginWithB);
}
输出结果为:
2020-09-24 17:04:15.974855+0800 ChecksumsWarning[2479:18006076] 过滤掉不是以b开始的字符串:(
Bbb
)
5、占位符
a、占位符参数
- (void)placeholderDemo
{
NSString *name = @"name";
NSString *value = @"齐天大圣";
NSDictionary *ditc = @{@"name":@"我是齐天大圣孙悟空水帘洞花果山大王"};
// 创建谓词,该谓词中包含了2个占位符,相当于创建了谓词表达式 "name CONTAINS '齐天大圣'" 字典中的键为name的值是否包含"齐天大圣"
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K contains %@",name, value];
// 使用谓词执行判断
BOOL isContain = [predicate evaluateWithObject:ditc];
if (isContain)
{
NSLog(@"字典中的键为name的值包含齐天大圣");
}
else
{
NSLog(@"字典中的键为name的值不包含齐天大圣");
}
}
输出结果为:
2020-09-24 16:18:24.592350+0800 ChecksumsWarning[1783:17966853] 字典中的键为name的值包含齐天大圣
b、设置变量值
- (void)SUBSTRdemo
{
// $SUBSTR相当于一个变量,需要我们调用时为它设置值
NSPredicate* predicateTemplate = [NSPredicate predicateWithFormat:@"%K CONTAINS $SUBSTR" , @"number"];
// 使用NDDictionary指定SUBSTR的值为'50',这就相当于创建了谓词表达式"pass CONTAINS '50'"
NSPredicate* predicate = [predicateTemplate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObjectsAndKeys:@"50",@"SUBSTR", nil]];
// 使用谓词执行判断
NSDictionary *ditc = @{@"number":@"50000123432425432"};
BOOL isContain = [predicate evaluateWithObject:ditc];
if (isContain)
{
NSLog(@"字典中的键为number的值包含50");
}
else
{
NSLog(@"字典中的键为number的值不包含50");
}
}
输出结果为:
2020-09-24 16:35:53.575536+0800 ChecksumsWarning[1992:17978505] 字典中的键为number的值包含50
6、正则表达式
- (void)regularExpressionsDemo
{
NSArray *array = @[@"TATACCATGGGCCATCATCATCATCATCATCATCATCATCATCACAG",
@"CGGGATCCCTATCAAGGCACCTCTTCG", @"CATGCCATGGATACCAACGAGTCCGAAC",
@"CAT", @"CATCATCATGTCT", @"DOG"];
// 查找包含至少3个“CAT”序列重复的字符串,但后面没有“CA”
NSPredicate *catPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES '.*(CAT){3,}(?!CA).*'"];
NSArray *filteredArray = [array filteredArrayUsingPredicate:catPredicate];
NSLog(@"查找包含至少3个CAT序列重复的字符串,但后面没有CA:%@",filteredArray);
}
输出结果为:
2020-09-24 16:40:32.491094+0800 ChecksumsWarning[2084:17983367] 查找包含至少3个“CAT”序列重复的字符串,但后面没有“CA”:(
CATCATCATGTCT
)
7、空值
- (void)nullPredicateDemo
{
NSString *firstName = @"Xie";
NSArray *array = @[ @{ @"lastName" : @"JiaPei" }, @{ @"firstName" : @"Wang", @"lastName" : @"ErDe", @"birthday":[NSDate date]},@{ @"firstName" : @"Xie", @"lastName" : @"LingYun", @"birthday":[NSDate date]}];
// 姓为Xie或者为空
NSPredicate *predicateForNull = [NSPredicate predicateWithFormat:@"(firstName == %@) || (firstName = nil)", firstName];
// 使用谓词执行判断
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicateForNull];
NSLog(@"过滤后的数组为: %@", filteredArray);
BOOL ok = [predicateForNull evaluateWithObject: [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"firstName"]];
if (ok)
{
NSLog(@"存在姓为Xie或者为空");
}
else
{
NSLog(@"不存在姓为Xie或者为空");
}
}
输出结果为:
2020-09-24 16:51:12.268705+0800 ChecksumsWarning[2267:17993506] 过滤后的数组为: (
{
lastName = JiaPei;
},
{
birthday = "2020-09-24 08:51:12 +0000";
firstName = Xie;
lastName = LingYun;
}
)
2020-09-24 16:51:12.268825+0800 ChecksumsWarning[2267:17993506] 存在姓为Xie或者为空
8、复合谓词
- (void)compoundPredicateDemo
{
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF > 10"];
NSLog(@"predicate1 = %@", [predicate1 predicateFormat]);
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"SELF < 50"];
NSLog(@"predicate2 = %@", [predicate2 predicateFormat]);
// NSAndPredicateType 多个谓词表达式之间添加AND,NSOrPredicateType 多个谓词表达式之间添加OR
NSCompoundPredicate *compound = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[predicate1, predicate2]];
NSLog(@"compound = %@", [compound predicateFormat]);
BOOL result = [compound evaluateWithObject:@20];
if (result)
{
NSLog(@"20在区间(20,50)内");
}
else
{
NSLog(@"20不在区间(20,50)内");
}
}
输出结果为:
2020-09-24 17:17:16.746394+0800 ChecksumsWarning[2669:18016834] predicate1 = SELF > 10
2020-09-24 17:17:16.746510+0800 ChecksumsWarning[2669:18016834] predicate2 = SELF < 50
2020-09-24 17:17:16.746617+0800 ChecksumsWarning[2669:18016834] compound = SELF > 10 AND SELF < 50
2020-09-24 17:17:16.746715+0800 ChecksumsWarning[2669:18016834] 20在区间(20,50)内
9、Core Data中的使用
- (void)coreDataPredicate
{
NSManagedObjectContext *managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSInteger salaryLimit = 100;
// 查找收入超过指定金额的员工
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"salary > %@", salaryLimit];
[request setPredicate:predicate];
// 查询结果
NSError *error;
NSArray *resultArray = [managedObjectContext executeFetchRequest:request error:&error];
}
Demo
Demo在我的Github上,欢迎下载。
FoundationGrammarDemo