读 MBProgressHUD 感

话说,MBProgressHUD 是我接触iOS的第一个第三方的轮子,感觉还是很有感情的,一直一来也没好好看看里面,下面是大致看完后记录的几个点。

  • 利用KVO 刷新
  • 各种宏的巧用
  • 永远保证UIView 在主线程中进行动作

同时在想,MBProgressHUD 也有一个使用上的不方便是,弹出短时间内的提示框的时候,不能点击其他操作,这个很多时候是很不方便的。

一、利用 KVO 刷新
#pragma mark - KVO
- (void)registerForKVO {
    for (NSString *keyPath in [self observableKeypaths]) {
        [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];
    }
}

- (void)unregisterFromKVO {
    for (NSString *keyPath in [self observableKeypaths]) {
        [self removeObserver:self forKeyPath:keyPath];
    }
}

- (NSArray *)observableKeypaths {
    return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"labelColor",
            @"detailsLabelText", @"detailsLabelFont", @"detailsLabelColor", @"progress", @"activityIndicatorColor", nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO];
    } else {
        [self updateUIForKeypath:keyPath];
    }
}

- (void)updateUIForKeypath:(NSString *)keyPath {
    if ([keyPath isEqualToString:@"mode"] || [keyPath isEqualToString:@"customView"] ||
        [keyPath isEqualToString:@"activityIndicatorColor"]) {
        [self updateIndicators];
    } else if ([keyPath isEqualToString:@"labelText"]) {
        label.text = self.labelText;
    } else if ([keyPath isEqualToString:@"labelFont"]) {
        label.font = self.labelFont;
    } else if ([keyPath isEqualToString:@"labelColor"]) {
        label.textColor = self.labelColor;
    } else if ([keyPath isEqualToString:@"detailsLabelText"]) {
        detailsLabel.text = self.detailsLabelText;
    } else if ([keyPath isEqualToString:@"detailsLabelFont"]) {
        detailsLabel.font = self.detailsLabelFont;
    } else if ([keyPath isEqualToString:@"detailsLabelColor"]) {
        detailsLabel.textColor = self.detailsLabelColor;
    } else if ([keyPath isEqualToString:@"progress"]) {
        if ([indicator respondsToSelector:@selector(setProgress:)]) {
            [(id)indicator setValue:@(progress) forKey:@"progress"];
        }
        return;
    }
    [self setNeedsLayout];
    [self setNeedsDisplay];
}

获取属性,用KVO刷新,很巧妙,很直接,这个可以学习。

- (NSArray *)observableKeypaths;
二、 各种宏的巧用

区分ARC 的情况

#ifndef MB_INSTANCETYPE
#if __has_feature(objc_instancetype)
    #define MB_INSTANCETYPE instancetype
#else
    #define MB_INSTANCETYPE id
#endif
#endif

#ifndef MB_STRONG
#if __has_feature(objc_arc)
    #define MB_STRONG strong
#else
    #define MB_STRONG retain
#endif
#endif

#ifndef MB_WEAK
#if __has_feature(objc_arc_weak)
    #define MB_WEAK weak
#elif __has_feature(objc_arc)
    #define MB_WEAK unsafe_unretained
#else
    #define MB_WEAK assign
#endif
#endif

区分不同版本的

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
    #define MBLabelAlignmentCenter NSTextAlignmentCenter
#else
    #define MBLabelAlignmentCenter UITextAlignmentCenter
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
    #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \
        sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero;
#else
    #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero;
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
    #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
        boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \
        attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero;
#else
    #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
        sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero;
#endif

哎,想想还是顺便放到我另一个笔记中iOS 中常用宏,判断文字宽度不同版本的两者还是很实用的。

三、 永远保证UIView 在主线程中进行动作

  • show 时的判断
 NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread.");

  • KVO 刷新时的判断
 if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO];
    } else {
        [self updateUIForKeypath:keyPath];
    }

另外注意, 直接取消一个对象在当前Run Loop中的所有未执行的performSelector:withObject:afterDelay:方法所产生的Selector Sources

[NSObject cancelPreviousPerformRequestsWithTarget:self];

总的来说,其实在里面还是有多细节可以挖掘的,看我们的关注点吧

- (void)layoutSubviews;
- (void)drawRect:(CGRect)rect;

像上述两个方法中有很多可以去发现,同时要进行一些额外的操作也可以在这里面进行添加或修改。

像之前想的问题,弹出短时间内的提示框的时候,不能点击其他操作, 也许一个简单的交互就可以实现:

hud.userInteractionEnabled = NO;

又或是通过设置添加一个取消按钮也可以,当然这样更好。

而真正使用MBProgressHUD 还是很简单的,直接看一个github中的源码的Demo 基本都会啦。

备注下:以上是 Version 0.9.2中的一些点,而最新版本中已经有很多不同啦,可以再次学习,

你可能感兴趣的:(读 MBProgressHUD 感)