iOS常見容易出錯問題checklist

1:數組NSArrayNSMutableArray添加元素,進行插入數據不能爲nil。

2:數組NSArrayNSMutableArray越界檢查。

3:字典NSDictionary NSMutableDictionary添加元素,value不能爲nil。

4:集合NSSetNSmutableSet數據操作,value不能爲nil。

- (void)addObject:(ObjectType)object;
- (void)removeObject:(ObjectType)object;

5NSJSONSerialization 操作對象不能爲nil。

+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt 
error:(NSError **)error;
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

6:delegate 做 是否響應respondsToSelector判斷。

7:block調用進行是否爲空判斷。

8:NSString , NSMutableString字符串處理越界。

- (NSString *)substringFromIndex:(NSUInteger)from;
- (NSString *)substringToIndex:(NSUInteger)to;
- (NSString *)substringWithRange:(NSRange)range;

9:NSAttributedString字符串處理越界。

- (void)addAttribute:(NSAttributedStringKey)name value:(id)value range:(NSRange)range;
- (void)removeAttribute:(NSAttributedStringKey)name range:(NSRange)range;

10:後臺返回數據,從json獲取某字段進行字符串或者其他類型方法操作,需對該字段判斷是否爲字符串類型或者其他類型判斷。避免對後臺返回NSNull做操作導致崩潰。

我們在公共基礎組件增加了NSObject分類(NSObject+TypeConver.h),導致崩潰。對5種常用類型進行檢查,大家可以直接使用。

//int類型檢查
- (NSInteger)intFromValue:(NSObject *)value
{
    if ([value isKindOfClass:[NSNumber class]])
    {
        return  [(NSNumber *)value integerValue];
    }
    else if ([value isKindOfClass:[NSString class]])
    {
        return [(NSString *)value integerValue];
    }
    
    return 0;
}

//float類型檢查
- (CGFloat)floatFromValue:(NSObject *)value
{
    
    if ([value isKindOfClass:[NSNumber class]])
    {
        return  [(NSNumber *)value floatValue];
    }
    else if ([value isKindOfClass:[NSString class]])
    {
        return [(NSString *)value floatValue];
    }
    
    return 0;
}

//字符串類型檢查
- (NSString *)stringFromValue:(NSObject *)value
{
    if ([value isKindOfClass:[NSString class]])
    {
        return (NSString *)value;
    }
    else if ([value isKindOfClass:[NSNumber class]])
    {
        return [(NSNumber *)value stringValue];
    }
    return nil;
}

//bool類型檢查
- (BOOL) booleanFromValue:(NSObject *)value
{
    if ([value isKindOfClass:[NSNumber class]])
    {
        return [(NSNumber *)value boolValue];
    }
    else if ([value isKindOfClass:[NSString class]])
    {
        
        if ([self compareString1:(NSString *)value string2:@"true"]) {
            return YES;
            
        }
        else if ([self compareString1:(NSString *)value string2:@"false"])
        {
            return NO;
        }
        else if ([self compareString1:(NSString *)value string2:@"yes"])
        {
            return YES;
        }
        else if ([self compareString1:(NSString *)value string2:@"no"])
        {
            return NO;
        }
        else {
            return [(NSString *)value boolValue];
        }
    }
    
    return NO;
}

//時間類型檢查
- (NSDate *)dateFromValue:(NSObject *)value
{
    if ([value isKindOfClass:[NSDate class]]) {
        return (NSDate *)value;
    }
    else if ([value isKindOfClass:[NSNumber class]]) {
        return [NSDate dateWithTimeIntervalSince1970:[(NSNumber *)value doubleValue]];
    }
    else if ([value isKindOfClass:[NSString class]]) {
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setFormatterBehavior:NSDateFormatterBehavior10_4];
        [df setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
        [df setDateFormat:@"yyyy-MM-dd"];
        
        NSDate *result = [df dateFromString:(NSString *)value];
        
        return  result;;
    }
    return nil;
}
NULL:用於普通類型,例如NSInteger
nil:用於OC對象(除了類這個對象),給nil對象發送消息不會crash
Nil:用於Class類型對象的賦值(類是元類的實例,也是對象)
NSNull:用於OC對象的站位,一般會作爲集合中的佔位元素,給NSNull對象發送消息會crash的,後臺給我們返回的就是NSNull對象

11,KVO addObserverremoveObserver一定要成對出現對同一keypath多次removeObserver導致崩潰。

12,對沙盒目錄操作時,千萬確認不要直接對三個根文件夾:Documents、Library、temp直接做刪除操作,對文件操作路徑拼接做防空判斷。

13,延遲執行方法,注意原來執行的方法是否有防護處理需要同步在延遲執行方法裏面防護。

- (void)scrollToSafetyIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated {
    
    //增加防止數組越界崩潰
    if (self.chatArray.count <= indexPath.row) {
        LogI(TAG_MEETING, @"scrollToSafetyIndexPath:self.chatArray.count <= indexPath.row");
        return;
    }
    
    NSArray *objects = @[indexPath, @(scrollPosition), @(animated)];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedScrollToRowAtIndexPath:) object:objects];
    [self performSelector:@selector(delayedScrollToRowAtIndexPath:) withObject:objects afterDelay:0.005];
}

- (void)delayedScrollToRowAtIndexPath:(NSArray *)objects { 

    NSIndexPath *indexPath = [objects firstObject];
    UITableViewScrollPosition scrollPosition = [objects[1] integerValue];
    BOOL animated = [[objects lastObject] boolValue];
    
    //延遲執行方法裏面,必須跟着原來執行方法,增加防止數組越界崩潰
    if (self.chatArray.count <= indexPath.row) {
        LogI(TAG_MEETING, @"delayedScrollToRowAtIndexPath:self.chatArray.count <= indexPath.row");
        return;
    }

    [self.chatTableView scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];
}

14,對源文件進行NSFileManager複製,移動,刪除操作的時候,需要對源文件判斷是否存在,並做相應異常處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章