iOS原生開發(fā)展示數(shù)學(xué)公式的問(wèn)題

最近遇到的問(wèn)題,需求是展示服務(wù)端返回的一些文案,這是多么一個(gè)簡(jiǎn)單的展示啊,but偏偏出現(xiàn)了問(wèn)題,因?yàn)榉祷氐臄?shù)據(jù)是包含有一些數(shù)學(xué)公式的,但是返回的數(shù)據(jù)是這個(gè)樣子的

皮爾遜相似度是一種用于衡量?jī)蓚€(gè)變量之間線性相關(guān)程度的統(tǒng)計(jì)方法。其公式為:\[ r = \frac{\sum{(x_i - \bar{x})(y_i -?\bar{y})}}{\sqrt{\sum{(x_i - \bar{x})^2} \sum{(y_i - \bar{y})^2}}} \]

要求把返回的公式進(jìn)行按照對(duì)應(yīng)的數(shù)學(xué)公式進(jìn)行顯示,好吧,那只能翻箱倒柜去查查資料了,根據(jù)簡(jiǎn)書、deepseek、騰訊元寶、chatgpt等等多種ai工具的回復(fù),有三種解決方案

1、基于wkwebview進(jìn)行展示,這種是開發(fā)成本最低的一種,比較簡(jiǎn)單

//你的包含latex公式的文本
NSString * text = @"";

// 構(gòu)建包含MathJax的HTML字符串
NSString *htmlString = [NSString stringWithFormat:<!DOCTYPE html><html><head>? ? <meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>? ? <script type='text/javascript' async src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML'></script></head><body>? ? <div id='math'>%@</div>? ? <script type='text/javascript'>? ? ? ? MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'math']);? ? </script></body></html>, text];? ? ? ?

// 加載HTML字符串
[webView loadHTMLString:htmlString baseURL:nil]

2、第二種發(fā)現(xiàn)了一種第三方sdk,iosMath庫(kù):https://github.com/kostub/iosMath,比較開心的去接入,開始進(jìn)行coding,結(jié)果發(fā)現(xiàn)寫了一堆代碼,只展示了公式內(nèi)容,其他文本相關(guān)的一點(diǎn)沒(méi)有展示,如果只能展示公式相關(guān)的話,那只能說(shuō)自己去做字符串的拆分,然后把普通文本和公式文本組成富文本去展示了


展示效果

字符串替換:發(fā)現(xiàn)iosMath不支持\(、\)、\[、\]這種類型的語(yǔ)法,然后把這種字符串替換為$符號(hào)

- (NSString *)replaceForLaTeXOriString:(NSString *)oldValue{

? ? //iosMath不支持\(、\)、\[、\],將這兩種轉(zhuǎn)為$來(lái)匹配

? ? NSString * pattern = @"(\\\\\\))|(\\\\\\()|(\\\\\\[\\s*)|(\\s*\\\\])";


? ? NSError*error =nil;

? ? // 創(chuàng)建正則表達(dá)式對(duì)象

? ? NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];

? ? // 執(zhí)行替換,將匹配到的模式替換為 $

? ? NSString * newValue = [regex stringByReplacingMatchesInString:oldValue options:0 range:NSMakeRange(0, oldValue.length) withTemplate:@"$"];

? ? returnnewValue;

}

字符串切割:

- (NSAttributedString *)attributedStringWithLeTeXString:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor maxWidth:(CGFloat)maxWidth{

? ? self.maxWidth = maxWidth;

? ? text = [self replaceForLaTeXOriString:text];

? ? NSArray * tmpArr = [self matchString:text toRegexString:@"\\$.*?\\$"];

? ? NSMutableAttributedString * totalAttrString = [[NSMutableAttributedString alloc] init];

? ? for (KGLaTeXModel * model in tmpArr) {

? ? ? ? NSMutableAttributedString * attrString;

? ? ? ? if (model.isLaTeX) {

? ? ? ? ? ? attrString = [self getMaxLatexWithString:model.text font:font textColor:textColor].mutableCopy;

? ? ? ? }

? ? ? ? if (attrString) {

? ? ? ? ? ? [totalAttrString appendAttributedString:attrString];

? ? ? ? }else{

? ? ? ? ? ? attrString = [[NSMutableAttributedString alloc] initWithString:model.text];

? ? ? ? ? ? [attrString addAttributes:@{

? ? ? ? ? ? ? ? NSFontAttributeName : font,

? ? ? ? ? ? ? ? NSForegroundColorAttributeName : textColor,

? ? ? ? ? ? } range:NSMakeRange(0, model.text.length)];

? ? ? ? ? ? [totalAttrString appendAttributedString:attrString];

? ? ? ? }

? ? }

? ? return totalAttrString;

}

把文本根據(jù)$xxxx$做分割成不同的字符串

- (NSArray *)matchString:(NSString *)string toRegexString:(NSString *)regexStr{


? ? if(string.length == 0){

? ? ? ? return nil;

? ? }


? ? NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:nil];


? ? NSArray * matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];


? ? //match: 所有匹配到的字符,根據(jù)() 包含級(jí)


? ? NSMutableArray *array = [NSMutableArray array];


? ? NSInteger location = 0;


? ? for (NSTextCheckingResult *match in matches) {

? ? ? ? //以正則中的(),劃分成不同的匹配部分

? ? ? ? if (match.range.location == NSNotFound) {

? ? ? ? ? ? continue;

? ? ? ? }


? ? ? ? if (match.range.location != location) {

? ? ? ? ? ? NSRange range = NSMakeRange(location, match.range.location - location);

? ? ? ? ? ? KGLaTeXModel * model = [[KGLaTeXModel alloc] init];

? ? ? ? ? ? model.text = [string substringWithRange:range];

? ? ? ? ? ? model.range = range;

? ? ? ? ? ? model.isLaTeX = NO;

? ? ? ? ? ? [array addObject:model];

? ? ? ? }

? ? ? ? KGLaTeXModel * model = [[KGLaTeXModel alloc] init];

? ? ? ? model.text = [string substringWithRange:match.range];

? ? ? ? model.range = match.range;

? ? ? ? model.isLaTeX = YES;

? ? ? ? [array addObject:model];

? ? ? ? location = match.range.location + match.range.length;

? ? }


? ? if (location != string.length - 1) {

? ? ? ? NSRange range = NSMakeRange(location, string.length - location);

? ? ? ? KGLaTeXModel * model = [[KGLaTeXModel alloc] init];

? ? ? ? model.text = [string substringWithRange:range];

? ? ? ? model.range = range;

? ? ? ? model.isLaTeX = NO;

? ? ? ? [array addObject:model];

? ? }


? ? return array;

}

把latex公式文本轉(zhuǎn)成富文本

- (NSAttributedString*)getMaxLatexWithString:(NSString*)latexStr? font:(UIFont*)fonttextColor:(UIColor*)textColor{


? ? MTMathUILabel* label = [[MTMathUILabel alloc] init];

? ? label.fontSize= font.pointSize;

? ? label.textColor= textColor;

? ? label.latex= latexStr;


? ? CGSizesize = [labelsizeThatFits:CGSizeMake(self.maxWidth,MAXFLOAT)];

? ? if(CGSizeEqualToSize(size,CGSizeZero)) {

? ? ? ? returnnil;

? ? }

? ? label.frame=CGRectMake(0,0, size.width, size.height);


? ? UIView* view = [[UIViewalloc]initWithFrame:CGRectMake(0,0, size.width, size.height+5)];

? ? [viewaddSubview:label];

? ? label.frame=CGRectMake(0,0, size.width, size.height);


? ? NSTextAttachment * attach = [[NSTextAttachment alloc] init];

? ? attach.bounds = CGRectMake(0, -view.frame.size.height/2.0, view.frame.size.width, view.frame.size.height);

? ? attach.image= [selfimageWithView:viewsize:view.frame.size];

? ? return [NSAttributedString attributedStringWithAttachment:attach];

}

調(diào)用方式:

? ? NSAttributedString * attrString = [GetLaTeXTool attributedStringWithLeTeXString:@"你的文本" font:[UIFont systemFontOfSize:15 weight:UIFontWeightMedium] textColor:UIColor.orangeColor maxWidth:300];

? ? self.label.attributedText= attrString;

我這邊用到的文本,數(shù)學(xué)公式、化學(xué)公式、物理公式

? ? self.textArray = @[

? ? ? ? @"\\[\n? 4\\text{Fe} + 3\\text{O}_2 \\rightarrow 2\\text{Fe}_2\\text{O}_3\n? \\]\n",

? ? ? ? @"\\[ g = \\frac{G \\cdot M}{R^2} \\]\n\n",

? ? ? ? @"\\[ (i\\gamma^\\mu \\partial_\\mu - m)\\psi = 0 \\]\n\n",

? ? ? ? @"$ \\because a==b $",

? ? ? ? @"皮爾遜相似度是一種用于衡量?jī)蓚€(gè)變量之間線性相關(guān)程度的統(tǒng)計(jì)方法。",

? ? ? ? @"其公式為:\n\n",

? ? ? ? @"\\[ r = \\frac{\\sum{(x_i - \\bar{x})(y_i - ",

? ? ? ? @"\\bar{y})}}{\\sqrt{\\sum{(x_i - \\bar{x})^2} \\sum{(y_i - \\bar{y})^2}}} \\]\n\n",

? ? ? ? @"其中:\n",

? ? ? ? @"- \\( x_i \\) 和 \\( y_i \\)分別是兩個(gè)變量的觀測(cè)值。\n",

? ? ? ? @"- \\( \\bar{x} \\) 和 \\( \\bar{y} \\) 分別是兩個(gè)變量的平均值。\n",

? ? ? ? @"- \\( r \\) 的取值范圍為 -1 到 1,1 表示完全正相關(guān),",

? ? ? ? @"-1 表示完全負(fù)相關(guān),",

? ? ? ? @"0 表示無(wú)線性相關(guān)。\n\n",

? ? ? ? @"皮爾遜相似度常用于統(tǒng)計(jì)分析、推薦系統(tǒng)等領(lǐng)域,",

? ? ? ? @"用來(lái)評(píng)估變量之間的線性關(guān)系。",

? ? ];

如果遇到了一些不支持的符號(hào),可以通過(guò)下邊這個(gè)方法去添加

比如說(shuō)because不支持,$ \\because a==b $無(wú)法正常展示

[self addLatexSymbol:@"because" andEscapedString:@"∵"];

- (void)addLatexSymbol:(NSString*)symbolandEscapedString:(NSString*)escapedString{

? ? //添加iosMath一些不支持的轉(zhuǎn)義字符

? ? [MTMathAtomFactory addLatexSymbol:symbol value:[MTMathAtomFactory operatorWithName:escapedString limits:NO]];

}

基本上完事了

3、第三種方案,我看推薦的是使用CoreText,因本人水平有限,就不巴巴了

4、swiftUI有一個(gè)LaTeXSwiftUI庫(kù),這個(gè)庫(kù)有個(gè)限制就是最低得iOS16版本才行


有需要的可以下載下我寫的demo:https://github.com/371726787/latexForTest

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容