第三方类MBProcessHUD的阅读和理解

来源:互联网 发布:导出来的sql带双引号 编辑:程序博客网 时间:2024/03/28 19:38

平常做项目没时间是不会在意一些第三方类的具体实现,稍作了解后便直接用,这两天闲下来,具体看了看MBProcessHUD这个类。下面谈谈看法

MBProcesHUD这个类主要是实现一些消息提醒,具体的比如加载中,加载失败或者其他任何你想的提示!

在这个类的实现中,有一个值得注意的是采用的是键值观察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", @"detailsLabelText", @"detailsLabelFont", @"progress", 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];}}

通过如果对象的属性发生了改变,则通过观察者的回调函数,进行UI上面的更改,也即是updateUIForKeypath这个函数

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

而在updateUIForKeypath这个函数中,主要是针对键值变化,最后进行UI上的由[self setNeedsLayout] 和[self setNeedsDisplay]进行重绘。这两个函数分别调用layoutSubviews和drawRect这两个函数UI上重绘

- (void)drawRect:(CGRect)rect {CGContextRef context = UIGraphicsGetCurrentContext();UIGraphicsPushContext(context);if (self.dimBackground) {//Gradient colourssize_t gradLocationsNum = 2;CGFloat gradLocations[2] = {0.0f, 1.0f};CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum);CGColorSpaceRelease(colorSpace);//Gradient centerCGPoint gradCenter= CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);//Gradient radiusfloat gradRadius = MIN(self.bounds.size.width , self.bounds.size.height) ;//Gradient drawCGContextDrawRadialGradient (context, gradient, gradCenter, 0, gradCenter, gradRadius, kCGGradientDrawsAfterEndLocation);CGGradientRelease(gradient);}    // Set background rect color    if (self.color) {        CGContextSetFillColorWithColor(context, self.color.CGColor);    } else {        CGContextSetGrayFillColor(context, 0.0f, self.opacity);    }// Center HUDCGRect allRect = self.bounds;// Draw rounded HUD backgroud rectCGRect boxRect = CGRectMake(roundf((allRect.size.width - size.width) / 2) + self.xOffset,roundf((allRect.size.height - size.height) / 2) + self.yOffset, size.width, size.height);float radius = 10.0f;CGContextBeginPath(context);CGContextMoveToPoint(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect));CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMinY(boxRect) + radius, radius, 3 * (float)M_PI / 2, 0, 0);CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMaxY(boxRect) - radius, radius, 0, (float)M_PI / 2, 0);CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMaxY(boxRect) - radius, radius, (float)M_PI / 2, (float)M_PI, 0);CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect) + radius, radius, (float)M_PI, 3 * (float)M_PI / 2, 0);CGContextClosePath(context);CGContextFillPath(context);UIGraphicsPopContext();}

- (void)layoutSubviews {// Entirely cover the parent viewUIView *parent = self.superview;if (parent) {self.frame = parent.bounds;}CGRect bounds = self.bounds;// Determine the total widt and height neededCGFloat maxWidth = bounds.size.width - 4 * margin;CGSize totalSize = CGSizeZero;CGRect indicatorF = indicator.bounds;indicatorF.size.width = MIN(indicatorF.size.width, maxWidth);totalSize.width = MAX(totalSize.width, indicatorF.size.width);totalSize.height += indicatorF.size.height;CGSize labelSize = [label.text sizeWithFont:label.font];labelSize.width = MIN(labelSize.width, maxWidth);totalSize.width = MAX(totalSize.width, labelSize.width);totalSize.height += labelSize.height;if (labelSize.height > 0.f && indicatorF.size.height > 0.f) {totalSize.height += kPadding;}CGFloat remainingHeight = bounds.size.height - totalSize.height - kPadding - 4 * margin; CGSize maxSize = CGSizeMake(maxWidth, remainingHeight);CGSize detailsLabelSize = [detailsLabel.text sizeWithFont:detailsLabel.font constrainedToSize:maxSize lineBreakMode:detailsLabel.lineBreakMode];totalSize.width = MAX(totalSize.width, detailsLabelSize.width);totalSize.height += detailsLabelSize.height;if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) {totalSize.height += kPadding;}totalSize.width += 2 * margin;totalSize.height += 2 * margin;// Position elementsCGFloat yPos = roundf(((bounds.size.height - totalSize.height) / 2)) + margin + yOffset;CGFloat xPos = xOffset;indicatorF.origin.y = yPos;indicatorF.origin.x = roundf((bounds.size.width - indicatorF.size.width) / 2) + xPos;indicator.frame = indicatorF;yPos += indicatorF.size.height;if (labelSize.height > 0.f && indicatorF.size.height > 0.f) {yPos += kPadding;}CGRect labelF;labelF.origin.y = yPos;labelF.origin.x = roundf((bounds.size.width - labelSize.width) / 2) + xPos;labelF.size = labelSize;label.frame = labelF;yPos += labelF.size.height;if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) {yPos += kPadding;}CGRect detailsLabelF;detailsLabelF.origin.y = yPos;detailsLabelF.origin.x = roundf((bounds.size.width - detailsLabelSize.width) / 2) + xPos;detailsLabelF.size = detailsLabelSize;detailsLabel.frame = detailsLabelF;// Enforce minsize and quare rulesif (square) {CGFloat max = MAX(totalSize.width, totalSize.height);if (max <= bounds.size.width - 2 * margin) {totalSize.width = max;}if (max <= bounds.size.height - 2 * margin) {totalSize.height = max;}}if (totalSize.width < minSize.width) {totalSize.width = minSize.width;} if (totalSize.height < minSize.height) {totalSize.height = minSize.height;}self.size = totalSize;}



0 0