iOS development judge whether the array is empty

AFNetworking is our common three-party library. We need to operate the requested responseobject. In many cases, we can't reach a consensus with the background or achieve perfect filtering, which will lead to program crash. For example, the background default data is an array, but a string or null value is given. At this time, you can call array.count, which will cause crash. In order to avoid such errors, we need to filter the data comprehensively.

Many people give a method to judge whether an array is empty

if (array != nil && ![array isKindOfClass:[NSNull class]] && array.count != 0){
     //Perform the operation when array is not empty 
}

Strictly speaking, such a judgment is wrong. When array is not [NSArray class], calling array.count will crash

Let's do an experiment

 NSObject *obj = [NSObject new];
 NSArray *array = (NSArray *)obj;
 NSLog(@"---%@",array);
 NSLog(@"---%ld",array.count);

output

---<NSObject: 0x600001dcc2d0>
-[NSObject count]: unrecognized selector sent to instance 0x600001dcc2d0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSObject count]: unrecognized selector sent to instance 0x600001dcc2d0'

When receiving an object with array, (NSArray *) does not cast, it just tells the compiler that your receiving object is [NSArray class], which can eliminate at most warnings. This results in an error when you receive the data corresponding to a field of responseobject with an array. You think you converted the data into [NSArray class], but you didn't

Give an example

 NSDictionary *dic = @{@"a": @"123"};
 NSArray *array = (NSArray *)dic[@"a"];
 NSLog(@"---%@",array);
---123

Visible receive object is a string. If array.count is called at this time, it will crash.
So when calling array.count or other array methods, it's best to determine whether the object is [NSArray class]

Here's my approach

#pragma mark determines whether it is an array
+(BOOL)isArray:(NSArray *)array{
    
    if (array == nil) {
        return NO;
    }
    if ([array isKindOfClass:[NSNull class]]) {
        return NO;
    }
    if (![array isKindOfClass:[NSArray class]]){
        return NO;
    }
    return YES;
}

In the same way, whether it is a dictionary or not, string is the same

#pragma mark determines whether it is a dictionary
+(BOOL)isDictionary:(NSDictionary *)dic{
    
    if (dic == nil) {
        return NO;
    }
    if ([dic isKindOfClass:[NSNull class]]) {
        return NO;
    }
    if (![dic isKindOfClass:[NSDictionary class]]){
        return NO;
    }
    return YES;
}
#pragma mark determines whether it is a string
+(BOOL)isString:(NSString *)string{
    
    if (string == nil) {
        return NO;
    }
    if ([string isKindOfClass:[NSNull class]]) {
        return NO;
    }
    if (![string isKindOfClass:[NSString class]]){
        return NO;
    }
    if ([string isEqualToString:@"null"]) {
        return NO;
    }
    if ([string isEqualToString:@"<null>"]) {
        return NO;
    }
    return YES;
}

The above is my summary method, for reference only. If there is something not considered in place, please point out. Thank you

Posted by austine_power007 on Wed, 04 Dec 2019 21:59:28 -0800