ios – stringByReplacingOccurrencesOfString没有给我想要的结果

ios – stringByReplacingOccurrencesOfString没有给我想要的结果,第1张

概述我有一些NSString喜欢: test = @"this is %25test%25 string"; 我试图用一些阿拉伯语文本替换测试,但它并没有完全取代它: [test stringByReplacingOccurrencesOfString:@"test" withString:@"اختبار"]; 结果是: this is %25 اختبار %25 string 我读到的一些地方可 我有一些Nsstring喜欢:

test = @"this is %25test%25 string";

我试图用一些阿拉伯语文本替换测试,但它并没有完全取代它:

[test stringByReplacingOccurrencesOfString:@"test" withString:@"اختبار"];

结果是:

this is %25 اختبار %25 string

我读到的一些地方可能存在编码或文本对齐方面的问题.是否需要对阿拉伯字符串 *** 作进行额外的调整.

编辑:我已经使用了NSMutable字符串插入属性,但结果仍然相同.

解决方法 编辑2:

另一件事发生在我这个特定的例子中造成了大部分麻烦.您上面有一个部分百分比编码的字符串.你有空格,但你也有%.你应该避免这样做.百分比编码字符串或不编码.在需要时立即转换所有内容(使用stringByAddingPercentEscapesUsingEnCoding :).不要试图“硬编码”百分比编码.如果您刚刚使用“这是一个%اختبار%字符串”(然后在结尾处对整个事物进行百分比编码),那么所有的方向问题都会消失(看看它如何呈现正常?).当你真正需要处理方向性时,其余的这些答案解决了更普遍的问题.

编辑:

该行之后的原始答案与人类可读的字符串相关,并且对于人类可读的字符串是正确的,但您的实际问题(基于您的后续跟踪)是关于URL的. URL不是人类可读的字符串,即使它们偶尔看起来像它们.它们是一系列字节,与它们呈现给人类的方式无关. “اختبار”不能位于URL的路径或片段部分.这些字符不属于这些部分的合法字符集(允许اختبار成为主机的一部分,但您必须遵循IDN规则).

正确的URL编码是%< arabic>%字符串是:

this%20is%20a%20%2525%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1%2525%20string

如果您将此字符串解码并渲染到屏幕,它将显示如下:

this is a %25اختبار%25 string

但它实际上就是你所指的字符串(它是你应该传递给浏览器的字符串).按照字节(就像计算机一样):

this   - this    (Alpha)%20    - <space> (encoded)is     - is      (Alpha)%20    - <space> (encoded)a      - a       (Alpha)%20    - <space> (encoded)%25    - %       (encoded)25     - 25      (DIGIT)%D8%A7 - ا       (encoded)%D8%AE - خ       (encoded)%D8%AA - ت       (encoded)%D8%A8 - ب       (encoded)%D8%A7 - ا       (encoded)%D8%B1 - ر       (encoded)%25    - %       (encoded) 25     - 25      (DIGIT)%20    - <space> (encoded)string - string  (Alpha)

Unicode BIDI显示算法正在做它意味着要做的事情;它不是你所期望的.但那些是字节,它们的顺序正确.如果您向此字符串添加任何其他字节(如LRO),那么您正在修改URL,这意味着不同的东西.

所以你需要回答的问题是,你是在创建一个URL,还是在制作一个人类可读的字符串?如果你正在制作一个URL,它应该是URL编码的,在这种情况下你不会有这个显示问题(除非这是主机的一部分,这是一套不同的规则,但我不相信这是你的问题).如果这是一个人类可读的字符串,请参阅下面有关如何为BIDI算法提供提示和覆盖的信息.

您可能真的需要两者(人性化的字符串和可以粘贴的正确URL).没关系,你只需要自己处理剪贴板.显示字符串,但是当用户去复制它时,使用UIPasteboard或通过覆盖copy:将其替换为完全编码的URL.请参阅Copy,and Paste Operations.这是相当常见的(注意在Safari中,它在地址栏中只显示“stackoverflow.com”,但如果您复制并粘贴它,它会粘贴“https://stackoverflow.com/”同样的事情.

原始答案与人类可读的字符串有关.

信不信由你,stringByReplacingOccuranceOfString:正在做正确的事情.它只是没有显示你期望的方式.如果你走过characteratIndex:,你会发现它是:

% 2 5 ا ...

问题是布局引擎在所有“中性方向”字符周围变得非常混乱.引擎无法理解您是否将“%”连接到左侧到右侧部分或从右到左部分.你必须通过给它一些明确的方向字符来帮助它.

有几种方法可以解决这个问题.首先,您可以使用Explicit Directional Isolates以Unicode 6.3 tr9-29方式完成.这正是Isolates要解决的问题.你有一些文本,你想要的方向完全独立于所有其他文本.我认为iOS或OS X实际上并不支持Unicode 6.3,但对于许多(尽管不是全部)用途,它“有效”.

你想用FSI(FirsT STRONG ISolATE U 2068)和PDI(POP DIRECTIONAL ISolATE U 2069)包围您的阿拉伯语.您也可以使用Rli(RIGHT-TO-left ISolATE)来显式化. FSI意味着“将此文本视为您找到的第一个强大角色的方向”.

所以你可以理想地做到这一点:

Nsstring *test = @"this is a %25\u2068test\u2069%25 string";Nsstring *arabic = @"اختبار";Nsstring *result = [test stringByReplacingOccurrencesOfString:@"test" withString:arabic];

如果您事先知道要替换的内容(那么您知道将FSI和PDI放在何处),那就行了.如果你不这样做,你可以用另一种方式做,并使其成为替代的一部分:

Nsstring * const FSI = @"\u2068";Nsstring * const PDI = @"\u2069";Nsstring *test = @"this is %25test%25 string";Nsstring *arabic = @"اختبار";Nsstring *replaceString = [@[FSI,arabic,PDI] componentsJoinedByString:@""];Nsstring *result = [test stringByReplacingOccurrencesOfString:@"test" withString:replaceString];

我说这“大多数”都有效.这对于UILabel来说很好,对于任何使用Core Text的东西来说都可能没问题.但在NSLog输出中,您将获得这些额外的“占位符”字符:

你也可以去其他地方.我还没有检查过UIWebVIEw.

所以还有其他一些选择.您可以使用方向标记.不过,这有点尴尬. LRM和RLM是零宽度强方向字符.所以你可以用LRM(左到右标记)括起阿拉伯语,这样阿拉伯语就不会打扰周围的文字.这有点难看,因为它意味着替代必须意识到它的替代品(这就是为什么隔离物被发明).

Nsstring * const LRM = @"\u200e";Nsstring *test = @"this is a %25test%25 string";Nsstring *replaceString = [@[LRM,LRM] componentsJoinedByString:@""];Nsstring *result = [test stringByReplacingOccurrencesOfString:@"test" withString:replaceString];

BTW,Directional Marks通常是正确的答案.它们应该始终是您尝试的第一件事.这个特殊问题有点太棘手了.

另一种方法是使用Explicit Directional OverrIDes.这些是巨大的“做我告诉你要做的事”的核心世界.你应该尽可能避免它们.他们存在一些安全问题,使得他们在某些地方被禁止(例如,< RLO> elgoog< pdf> .com将显示为Google.com).但他们会在这里工作.

使用LRO / pdf将整个字符串括起来强制它从左到右.然后,您将替换用RLO / pdf括起来强制它从右到左.同样,这是最后的手段,但它可以让您完全控制布局:

Nsstring * const LRO = @"\u202d";Nsstring * const RLO = @"\u202e";Nsstring * const pdf = @"\u202c";Nsstring *test = [@[LRO,@"this is a %25test%25 string",pdf] componentsJoinedByString:@""];Nsstring *arabic = @"اختبار";Nsstring *replaceString = [@[RLO,pdf] componentsJoinedByString:@""];Nsstring *result = [test stringByReplacingOccurrencesOfString:@"test" withString:replaceString];

我认为你可以使用显式定向嵌入字符来解决这个问题,但是我没有真正找到一种方法来做到这一点而没有至少一个覆盖(例如,你可以使用RLE而不是上面的RLO,但你仍然需要LRO).

这些应该为您提供所需的工具来解决所有问题.有关详细信息,请参阅Unicode TR9.如果您想更深入地了解问题和解决方案,请参阅Cal Henderson的优秀Understanding Bidirectional (BIDI) Text in Unicode.

总结

以上是内存溢出为你收集整理的ios – stringByReplacingOccurrencesOfString没有给我想要的结果全部内容,希望文章能够帮你解决ios – stringByReplacingOccurrencesOfString没有给我想要的结果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1076864.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存