你能看过来,就说明这个问题很好玩!IT开发是一个兴趣,更是一个挑战!兴趣使你工作有热情。挑战使让你工作充满刺激拉满的状态!我们日复一日年复一年的去撸代码,那些普普通通的功能代码,已经厌倦了!要的就是这种充满挑战最终攻克而带来快感!这种快感比那种快感让人感觉更得劲。。错了,可能是我老了吧~
因为业务开发需求,同样的功能三端(WEB、安卓 、iOS),而web端将数据封装成H5对应的标签方式,需要APP端来解析,将其文本提取出来倒没有什么技术难度,但核心问题是要取出相应的样式表渲染成正确的UI,这才是最困难的!
如<span style="color:orange,font-size:15px;">重要告警span>
要把它显示成如下的原生页面,怎么办呢?来分析一下这些标签的作用:
- 意思是将里面的文本加粗显示
-
- 标签普通的文本显示,但是文本的更多属性是在span的内联样式表中存放,我们要取出来颜色,字体大小来渲染为iOS的UILabel,通过setColor,setTextFont等API设置其显示样式!
我得到的原始数据为:
<a style="color:orange">【重要告警】a> <b>事件名称:b>CCE-CPU监控; <b>发生时间:b>2023-11-08 09:48:00 GMT+08:00; <b>事件源:b>AOM; <b>资源类型:b>Application; <b>指标名称:b>aom_container_cpu_usage; <b>最新指标值: b>45.95425; <b>命名空间:b>third-party; <b>容器名称:b>z-canal-test; <b>告警信息:b><br />阈值规则 CCE-CPU监控 状态从 “超限阈值” 变为 “正常” 。状态变化详细信息:指标名称为“aom_container_cpu_usage”,最新指标数据取值“45.954”,不满足阈值条件“>90”。; <b>修复建议:b>建议进入容器 z-canal-test查看资源使用情况;
最终实现的显示效果为:

下面业结合开源的三方库来实现此功能的显示,第三方库:TFHpple
-
- #if __has_include("TFHpple.h")
- #import "TFHpple.h"
- #endif
-
- @interface CSSStyleMap : NSObject
- + (NSDictionary *)cssColorMap;
-
- #if __has_include("TFHpple.h")
- + (UIColor *)colorFromCssText:(NSString *)ctext;
- + (NSMutableArray <NSMutableDictionary *>*)stylesFromElement:(TFHppleElement *)e;
- #endif
- @end
-
- @implementation CSSStyleMap
- //将CSS定义的颜色转为十六进制颜色
- + (NSDictionary *)cssColorMap
- {
- NSString *k = @"{\
- \"CLEAR\": \"#00000000\",\
- \"TRANSPARENT\": \"#00000000\",\
- \"\": \"#00000000\",\
- \"ALICEBLUE\": \"#F0F8FF\",\
- \"ANTIQUEWHITE\": \"#FAEBD7\",\
- \"AQUA\": \"#00FFFF\",\
- \"AQUAMARINE\": \"#7FFFD4\",\
- \"AZURE\": \"#F0FFFF\",\
- \"BEIGE\": \"#F5F5DC\",\
- \"BISQUE\": \"#FFE4C4\",\
- \"BLACK\": \"#000000\",\
- \"BLANCHEDALMOND\": \"#FFEBCD\",\
- \"BLUE\": \"#0000FF\",\
- \"BLUEVIOLET\": \"#8A2BE2\",\
- \"BROWN\": \"#A52A2A\",\
- \"BURLYWOOD\": \"#DEB887\",\
- \"CADETBLUE\": \"#5F9EA0\",\
- \"CHARTREUSE\": \"#7FFF00\",\
- \"CHOCOLATE\": \"#D2691E\",\
- \"CORAL\": \"#FF7F50\",\
- \"CORNFLOWERBLUE\": \"#6495ED\",\
- \"CORNSILK\": \"#FFF8DC\",\
- \"CRIMSON\": \"#DC143C\",\
- \"CYAN\": \"#00FFFF\",\
- \"DARKBLUE\": \"#00008B\",\
- \"DARKCYAN\": \"#008B8B\",\
- \"DARKGOLDENROD\": \"#B8860B\",\
- \"DARKGRAY\": \"#A9A9A9\",\
- \"DARKGREY\": \"#A9A9A9\",\
- \"DARKGREEN\": \"#006400\",\
- \"DARKKHAKI\": \"#BDB76B\",\
- \"DARKMAGENTA\": \"#8B008B\",\
- \"DARKOLIVEGREEN\": \"#556B2F\",\
- \"DARKORANGE\": \"#FF8C00\",\
- \"DARKORCHID\": \"#9932CC\",\
- \"DARKRED\": \"#8B0000\",\
- \"DARKSALMON\": \"#E9967A\",\
- \"DARKSEAGREEN\": \"#8FBC8F\",\
- \"DARKSLATEBLUE\": \"#483D8B\",\
- \"DARKSLATEGRAY\": \"#2F4F4F\",\
- \"DARKSLATEGREY\": \"#2F4F4F\",\
- \"DARKTURQUOISE\": \"#00CED1\",\
- \"DARKVIOLET\": \"#9400D3\",\
- \"DEEPPINK\": \"#FF1493\",\
- \"DEEPSKYBLUE\": \"#00BFFF\",\
- \"DIMGRAY\": \"#696969\",\
- \"DIMGREY\": \"#696969\",\
- \"DODGERBLUE\": \"#1E90FF\",\
- \"FIREBRICK\": \"#B22222\",\
- \"FLORALWHITE\": \"#FFFAF0\",\
- \"FORESTGREEN\": \"#228B22\",\
- \"FUCHSIA\": \"#FF00FF\",\
- \"GAINSBORO\": \"#DCDCDC\",\
- \"GHOSTWHITE\": \"#F8F8FF\",\
- \"GOLD\": \"#FFD700\",\
- \"GOLDENROD\": \"#DAA520\",\
- \"GRAY\": \"#808080\",\
- \"GREY\": \"#808080\",\
- \"GREEN\": \"#008000\",\
- \"GREENYELLOW\": \"#ADFF2F\",\
- \"HONEYDEW\": \"#F0FFF0\",\
- \"HOTPINK\": \"#FF69B4\",\
- \"INDIANRED\": \"#CD5C5C\",\
- \"INDIGO\": \"#4B0082\",\
- \"IVORY\": \"#FFFFF0\",\
- \"KHAKI\": \"#F0E68C\",\
- \"LAVENDER\": \"#E6E6FA\",\
- \"LAVENDERBLUSH\": \"#FFF0F5\",\
- \"LAWNGREEN\": \"#7CFC00\",\
- \"LEMONCHIFFON\": \"#FFFACD\",\
- \"LIGHTBLUE\": \"#ADD8E6\",\
- \"LIGHTCORAL\": \"#F08080\",\
- \"LIGHTCYAN\": \"#E0FFFF\",\
- \"LIGHTGOLDENRODYELLOW\": \"#FAFAD2\",\
- \"LIGHTGRAY\": \"#D3D3D3\",\
- \"LIGHTGREY\": \"#D3D3D3\",\
- \"LIGHTGREEN\": \"#90EE90\",\
- \"LIGHTPINK\": \"#FFB6C1\",\
- \"LIGHTSALMON\": \"#FFA07A\",\
- \"LIGHTSEAGREEN\": \"#20B2AA\",\
- \"LIGHTSKYBLUE\": \"#87CEFA\",\
- \"LIGHTSLATEGRAY\": \"#778899\",\
- \"LIGHTSLATEGREY\": \"#778899\",\
- \"LIGHTSTEELBLUE\": \"#B0C4DE\",\
- \"LIGHTYELLOW\": \"#FFFFE0\",\
- \"LIME\": \"#00FF00\",\
- \"LIMEGREEN\": \"#32CD32\",\
- \"LINEN\": \"#FAF0E6\",\
- \"MAGENTA\": \"#FF00FF\",\
- \"MAROON\": \"#800000\",\
- \"MEDIUMAQUAMARINE\": \"#66CDAA\",\
- \"MEDIUMBLUE\": \"#0000CD\",\
- \"MEDIUMORCHID\": \"#BA55D3\",\
- \"MEDIUMPURPLE\": \"#9370DB\",\
- \"MEDIUMSEAGREEN\": \"#3CB371\",\
- \"MEDIUMSLATEBLUE\": \"#7B68EE\",\
- \"MEDIUMSPRINGGREEN\": \"#00FA9A\",\
- \"MEDIUMTURQUOISE\": \"#48D1CC\",\
- \"MEDIUMVIOLETRED\": \"#C71585\",\
- \"MIDNIGHTBLUE\": \"#191970\",\
- \"MINTCREAM\": \"#F5FFFA\",\
- \"MISTYROSE\": \"#FFE4E1\",\
- \"MOCCASIN\": \"#FFE4B5\",\
- \"NAVAJOWHITE\": \"#FFDEAD\",\
- \"NAVY\": \"#000080\",\
- \"OLDLACE\": \"#FDF5E6\",\
- \"OLIVE\": \"#808000\",\
- \"OLIVEDRAB\": \"#6B8E23\",\
- \"ORANGE\": \"#FFA500\",\
- \"ORANGERED\": \"#FF4500\",\
- \"ORCHID\": \"#DA70D6\",\
- \"PALEGOLDENROD\": \"#EEE8AA\",\
- \"PALEGREEN\": \"#98FB98\",\
- \"PALETURQUOISE\": \"#AFEEEE\",\
- \"PALEVIOLETRED\": \"#DB7093\",\
- \"PAPAYAWHIP\": \"#FFEFD5\",\
- \"PEACHPUFF\": \"#FFDAB9\",\
- \"PERU\": \"#CD853F\",\
- \"PINK\": \"#FFC0CB\",\
- \"PLUM\": \"#DDA0DD\",\
- \"POWDERBLUE\": \"#B0E0E6\",\
- \"PURPLE\": \"#800080\",\
- \"RED\": \"#FF0000\",\
- \"ROSYBROWN\": \"#BC8F8F\",\
- \"ROYALBLUE\": \"#4169E1\",\
- \"SADDLEBROWN\": \"#8B4513\",\
- \"SALMON\": \"#FA8072\",\
- \"SANDYBROWN\": \"#F4A460\",\
- \"SEAGREEN\": \"#2E8B57\",\
- \"SEASHELL\": \"#FFF5EE\",\
- \"SIENNA\": \"#A0522D\",\
- \"SILVER\": \"#C0C0C0\",\
- \"SKYBLUE\": \"#87CEEB\",\
- \"SLATEBLUE\": \"#6A5ACD\",\
- \"SLATEGRAY\": \"#708090\",\
- \"SLATEGREY\": \"#708090\",\
- \"SNOW\": \"#FFFAFA\",\
- \"SPRINGGREEN\": \"#00FF7F\",\
- \"STEELBLUE\": \"#4682B4\",\
- \"TAN\": \"#D2B48C\",\
- \"TEAL\": \"#008080\",\
- \"THISTLE\": \"#D8BFD8\",\
- \"TOMATO\": \"#FF6347\",\
- \"TURQUOISE\": \"#40E0D0\",\
- \"VIOLET\": \"#EE82EE\",\
- \"WHEAT\": \"#F5DEB3\",\
- \"WHITE\": \"#FFFFFF\",\
- \"WHITESMOKE\": \"#F5F5F5\",\
- \"YELLOW\": \"#FFFF00\",\
- \"YELLOWGREEN\": \"#9ACD32\"\
- }";
-
- NSDictionary *map = [JsonKit jsonObject:k];
- return map;
- }
-
- #if __has_include("TFHpple.h")
- + (UIColor *)colorFromCssText:(NSString *)val
- {
- NSString *cl = [[CSSStyleMap cssColorMap] stringForKey:val];
- UIColor *color = nil;
- if (cl.length > 0)
- {
- color = [UIColor colorFromHex:cl];
- }
- else
- {
- val = [val stringByReplacingOccurrencesOfString:@"rgba(" withString:@""];
- val = [val stringByReplacingOccurrencesOfString:@"rgb(" withString:@""];
- val = [val stringByReplacingOccurrencesOfString:@")" withString:@""];
-
- NSArray *zlist = [val componentsSeparatedByString:@","];
- if (zlist.count >= 3)
- {
- color = [UIColor colorWithRed:[zlist[0] doubleValue]/255.0 green:[zlist[1] doubleValue]/255.0 blue:[zlist[2] doubleValue]/255.0 alpha:zlist.count>3?[zlist[3] doubleValue]:1];
- }
- }
-
- return color;
- }
-
-
- + (NSMutableArray <NSMutableDictionary *>*)stylesFromElement:(TFHppleElement *)e
- {
- NSString *b = [e content];
- NSArray <TFHppleElement *> *child = [e children];
- NSMutableArray *attributesList = [NSMutableArray arrayWithCapacity:0];
-
- [child enumerateObjectsUsingBlock:^(TFHppleElement * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if (![obj isTextNode])
- {
- /*企管只关注CSS样式中的color,backgroudColor,fontSize这三个属性,其余根据后期要求再解析展示
- CSS对于样式的定义为:color:orange,font-size:16px,background-color:xxx
- */
- NSDictionary *attrMap = [obj attributes];
- [attrMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop)
- {
- if (obj && [obj isKindOfClass:[NSString class]])
- {
- NSArray *plist = [obj componentsSeparatedByString:@","];
- [plist enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
- {
- NSArray *xlist = [obj componentsSeparatedByString:@":"];
- if ([xlist.firstObject isEqualToString:@"color"])
- {
- NSString *val = [[xlist lastObject] uppercaseString];
- UIColor *color = [CSSStyleMap colorFromCssText:val];
- if (color)
- {
- [attributesList addObject:@{@"fontColor":color,@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
- }
- }
- else if ([xlist.firstObject isEqualToString:@"background-color"])
- {
- NSString *val = [[xlist lastObject] uppercaseString];
- UIColor *color = [CSSStyleMap colorFromCssText:val];
- if (color)
- {
- [attributesList addObject:@{@"backgroundColor":color,@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
- }
- }
- else if ([xlist.firstObject isEqualToString:@"font-size"])
- {
- NSInteger val = [[xlist lastObject] integerValue];
- [attributesList addObject:@{@"fontSize":intToStr(val),@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
- }
- }];
- }
-
- }];
- }
- }];
-
- return attributesList;
- }
- #endif
- @end
页面使用:
- NSData *tdata = [cnt dataUsingEncoding:NSUTF8StringEncoding];
- TFHpple *doc = [[TFHpple alloc] initWithHTMLData:tdata];
- TFHppleElement *e = [[doc searchWithXPathQuery:@"//b"] firstObject];
-
- //包含解析出来的样式数据列表
- NSMutableArray <NSMutableDictionary *>*styleList = [CSSStyleMap stylesFromElement:e];
-
- //加粗
- NSMutableArray <NSValue *>*btagList = [rMap arrayForKey:@"bTag"];
- //a标签,跳转
- NSMutableArray <NSDictionary *>*atagList = [rMap arrayForKey:@"aTag"];
- //CSS样式
- NSMutableArray <NSDictionary *>*styleList = [rMap arrayForKey:@"style"];
-
- //textView是定义的UITextView的实例对象
-
- NSMutableAttributedString *mtext = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
- NSString *textStr = mtext.string;
- // NSArray *ranges = [self mutableRangeOfString:@"®[^\\s]+" targetString:textStr];
-
-
- [btagList enumerateObjectsUsingBlock:^(NSValue *a, NSUInteger idx, BOOL * _Nonnull stop)
- {
- [mtext addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:imTextFont(16)] range:a.rangeValue];
- }];
-
- [atagList enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
- {
- NSRange range = [(NSValue *)[obj objectForKey:@"range"] rangeValue];
- [mtext addAttribute:NSForegroundColorAttributeName value:[UIColor colorFromHex:@"#0000ee"] range:range];
-
- [mtext addAttribute:NSLinkTag value:[obj stringForKey:@"href"] range:range];
- }];
-
- [styleList enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
- {
- UIColor *fcolor = [obj objectForKey:@"fontColor"];
- NSRange range = [(NSValue *)[obj objectForKey:@"range"] rangeValue];
- [mtext addAttribute:NSForegroundColorAttributeName value:fcolor range:range];
- }];
-
- [textView setAttributedText:mtext];
这个示例只是展示其中一部分逻辑,你可以进行二次开发,扩展其功能,支持更多的属性的展示!
对了,肯定会有人说使用Webview直接加载就行了嘛,兄弟,我使用的场景是会话页面,你使用webview加载,就会存在性能体验问题!如果你全页面只有一个这样的消息,当然首选就是Webview,而我的页面如下,就不得不考虑用户体验!
