数组在我们日常的开发工作中可以说是最常见的了,但是今天我们不讲数组这么使用,我们说一说面向对象编程方式下数组的使用。
1. 使用自定义类封装数组
我们创建一个XSYArray的类,并且提供它的一些初始化方法。
@interface XSYArray : NSObject<NSCopying, NSMutableCopying>
// 数组的长度
@property (nonatomic, assign, readonly) NSInteger length;
+ (instancetype)array;
+ (instancetype)xsy_arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (instancetype)xsy_arrayWithArray:(NSArray *)array;
- (instancetype)xsy_initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
- (instancetype)xsy_initWithArray:(NSArray*)array;
XSYArray.m文件中对应的方法实现:
@interface XSYArray ()
@property (nonatomic, strong) NSMutableArray * data;
@end
@implementation XSYArray
+ (instancetype)array{
return [[self alloc] xsy_initWithArray:@[]];
}
+ (instancetype)xsy_arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION{
va_list argList;
NSMutableArray * temp = [NSMutableArray array];
if (firstObj) {
[temp addObject:firstObj];
va_start(argList, firstObj);
id obj;
while ((obj = va_arg(argList, id))) {
[temp addObject:obj];
}
}
va_end(argList);
return [[self alloc] xsy_initWithArray:temp];
}
+ (instancetype)xsy_arrayWithArray:(NSArray *)array{
return [[self alloc] xsy_initWithArray:array];
}
- (instancetype)xsy_initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION{
//VA_LIST 是在C语言中解决变参问题的一组宏
va_list argList;
if (firstObj) {
[self.data addObject:firstObj];
// VA_START宏,获取可变参数列表的第一个参数的地址,在这里指向firstObj
va_start(argList, firstObj);
// 临时指针变量
id obj;
// VA_ARG宏,获取当前可变参数,返回指定类型并将指针指向下一参数
// 首先 argList的内存地址指向的fristObj将对应储存的值取出,放在数组中,
// 并且将指针指向下一个参数,这样每次循环指针偏移量就不断下移直到取出nil
while ((obj = va_arg(argList, id))) {
[self.data addObject:obj];
}
}
// 清空列表
va_end(argList);
return [self init];
}
- (instancetype)xsy_initWithArray:(NSArray*)array{
_data = [NSMutableArray arrayWithArray:array];
return [self init];
}
- (instancetype)init{
if (self == [super init]) {
}
return self;
}
- (NSMutableArray *)data{
if (!_data) {
_data = [NSMutableArray array];
}
return _data;
}
- (NSInteger)length{
return self.data.count;
}
- (NSString *)description{
NSMutableString * mString = [NSMutableString stringWithString:@"["];
for (id obj in self.data) {
[mString appendString:[NSString stringWithFormat:@" %@,",obj]];
}
[mString appendString:@"]"];
return mString;
}
#pragma mark - NSCopying
- (id)copyWithZone:(nullable NSZone *)zone{
XSYArray * arr = [self.class new];
arr.data = _data;
return arr;
}
#pragma mark - NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone{
return [self copyWithZone:zone];
}
这样通过这些方法我们就可以创建出一个XSYArray对象类
2. 添加方法来实现数据操作
下面我们为这个XSYArray类添加一些增,删,改,查的方法
- (void)xsy_insertWithObject:(id)obj;
- (void)xsy_removeWithObject:(id)obj;
- (NSInteger)xsy_searchWithObject:(id)obj;
- (void)xsy_updateWithObject:(id)obj index:(NSInteger)idx;
- (NSArray *)xsy_allObjects;
- (void)xsy_removeAllObjects;
- (id)xsy_objectWithIndex:(NSInteger)idx;
- (void)xsy_enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL * stop))block;
XSYArray.m中对应的方法实现:
- (void)xsy_insertWithObject:(id)obj{
if (obj) {
[self.data addObject:obj];
}
else{
NSLog(@"insert object nil");
}
}
- (void)xsy_removeWithObject:(id)obj{
if (obj && [self.data containsObject:obj]) {
[self.data removeObject:obj];
NSLog(@"delete %@ success!",obj);
}
else{
NSLog(@"This %@ is not exist!",obj);
}
}
-(NSInteger)xsy_searchWithObject:(id)obj{
NSInteger idx = -1;
if (obj && [self.data containsObject:obj]) {
idx = [self.data indexOfObject:obj];
}
else{
NSLog(@"This %@ is not exist!",obj);
}
return idx;
}
- (void)xsy_updateWithObject:(id)obj index:(NSInteger)idx{
if (obj && (idx >= 0 && idx < self.data.count)) {
[self.data replaceObjectAtIndex:idx withObject:obj];
}
}
- (NSArray *)xsy_allObjects{
return self.data;
}
- (void)xsy_removeAllObjects{
[self.data removeAllObjects];
}
- (id)xsy_objectWithIndex:(NSInteger)idx{
if (idx >= 0 && idx < self.data.count) {
return [self.data objectAtIndex:idx];
}
return nil;
}
- (void)xsy_enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL * stop))block{
NSMutableArray * temp = self.data;
[temp enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (block) {
block(obj,idx,stop);
}
}];
}
数组中最常见的应该就是插入为nil而引发的奔溃问题:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
,通过对系统方法的封装,从而达到解决奔溃的问题。
下面我们测试一下这个类的使用:
- (void)viewDidLoad {
[super viewDidLoad];
XSYArray * array0 = [XSYArray array];
[array0 xsy_insertWithObject:@"a"];
[array0 xsy_insertWithObject:@"b"];
[array0 xsy_insertWithObject:@"c"];
NSLog(@"array0 ---- %@",array0);
[array0 xsy_removeWithObject:@"d"];
[array0 xsy_updateWithObject:@"d" index:2];
id obj = nil;
[array0 xsy_insertWithObject:obj];
NSInteger idx1 = [array0 xsy_searchWithObject:@"1"];
NSInteger idx2 = [array0 xsy_searchWithObject:@"b"];
NSLog(@"array0 ---- %@ , %ld , %ld",array0,idx1,idx2);
XSYArray * array1 = [[XSYArray alloc] xsy_initWithObjects:@"1",@"2",@"3",@"4",nil];
NSLog(@"array1 ----- %@",array1);
[array1 xsy_enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isEqualToString:@"3"]) {
*stop = YES;
}
NSLog(@"array1 --- obj %@, idx %ld , stop %p",obj,idx,stop);
}];
XSYArray * array3 = [array0 copy];
NSLog(@"array1 ----- %@ ,array3 ----- %@",array1,array3);
[array1 xsy_removeAllObjects];
NSLog(@"array1 ----- %@ ,array3 ----- %@",array1,array3);
}
打印结果:
array0 ---- [ a, b, c,]
This d is not exist!
insert object nil
This 1 is not exist!
array0 ---- [ a, b, d,] , -1 , 1
array1 ----- [ 1, 2, 3, 4,]
array1 --- obj 1, idx 0 , stop 0x7fff51b7099f
array1 --- obj 2, idx 1 , stop 0x7fff51b7099f
array1 --- obj 3, idx 2 , stop 0x7fff51b7099f
array1 ----- [ 1, 2, 3, 4,] ,array3 ----- [ a, b, d,]
array1 ----- [] ,array3 ----- [ a, b, d,]
网友评论