在swift中为iOS创build纯文本(Android格式)文本的属性string

我从Localizable.strings中读取string,其中包含类似于Android应用程序的strings.xml中的基本内容

"testShort" = "A <b>short</b>\ntest with another<b>bold text</b>"; 

粗体和换行是我在文本中唯一的两个格式属性。 我正在尝试开发这样的方法,现在几天没有成功:

 func ConvertText(inputText: String) -> NSAttributedString { // here comes the conversion to a representation with Helvetica 14pt and Helvetica-Bold 14pt including line feeds. } 

我最终的目标是在UITextView的属性文本中显示文本。

不熟悉Objective-C的Swift和iOS,我觉得很难做String操作,因为它们非常不同,也很复杂,所有的例子都在Objective-C中。 更难的是大多数API方法在Swift中不可用或不同于Objective-C中的…

这里是我在这里的许多其他职位的帮助下,迄今为止尝试的方法体:

 var test = inputText.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)! attrStr = NSAttributedString( data: test, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil, error: nil)! return attrStr 

这里的主要问题是\n没有被转换,而且字体非常小而且不同。

接下来,我尝试手动加粗文本的一部分。 这似乎是这样工作的:

 var newText = NSMutableAttributedString(string: inputText) newText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Bold", size: 14.0)!, range: NSRange(location:2,length:4)) 

现在我试图search文本中的属性,删除它们,并使用addAttribute类似的东西

 // Start of bold text var range = newText.rangeOfString("<b>")! // End of bold text var range2 = newText.rangeOfString("</b>")! // replacing attributes newText = newText.stringByReplacingCharactersInRange(range, withString: "") newText = newText.stringByReplacingCharactersInRange(range2, withString: "") // creating a range for bold => error "'String.Index' is not convertible to 'int'" // how to do such a thing var boldRange = NSMakeRange(range.startIndex, range2.endIndex -3) // setting bold newText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Bold", size: 14.0)!, range: boldRange) 

这一整个范围的事情是我目前的主要问题,因为它与string中的简单位置截然不同。

这个问题是缺乏(或隐藏)文档的一个很好的例子:

addAttribute一个NSRange, rangeOfString似乎根据我得到的错误消息提供了一个通用的范围 – 但是没有关于它的信息。 rangeOfString()中的Xcode中的“search文档”button导致NSString。 在那里searchrangeOfString()表示它返回NSRange 。 点击就会导致_NSRangetypes别名的信息,而这个信息又有两个名为locationlength NSUInteger属性。 我在XCode中看到的startIndex和endIndex属性在哪里? 很混乱…

如果你能给我一些片段或提示,我错了,甚至是方法体,那将是非常好的,因为如果你认识iOS和Swift,我还是希望它不是太难。 我瞄准的是iOS 7.1的支持,但如果它的方式更容易与iOS 8只罚款以及。

关于你使用NSAttributedString的第一个方法:

  • HTML中的\n字符只是普通的空格。 为了得到一个换行符,你必须先用<br />replace它。
  • 字体属性可以通过HTML <span> ,请参阅将HTMLparsing为NSAttributedText – 如何设置字体? 。

这给(现在更新为Swift 2):

 func convertText(inputText: String) -> NSAttributedString { var html = inputText // Replace newline character by HTML line break while let range = html.rangeOfString("\n") { html.replaceRange(range, with: "<br />") } // Embed in a <span> for font attributes: html = "<span style=\"font-family: Helvetica; font-size:14pt;\">" + html + "</span>" let data = html.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)! let attrStr = try? NSAttributedString( data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) return attrStr! } 

关于你的第二种方法:

有两个不同的rangeOfString()方法,一个用于(Swift) String和一个用于(Foundation) NSStringString方法返回一个Range<String.Index>NSString方法返回一个NSRange

这两者之间的转换是可能的,但是很复杂。 原因是在一个String每个“扩展String ”计为一个字符,而在NSString每个UTF-16计数。 一个扩展的字形集群可以是一个或多个UTF-16单元(“😄”是两个UTF-16单元,“🇩🇪”是四个)。

addAttribute()方法只接受一个NSRange 。 解决这个问题最简单的方法是将Swiftstring转换为NSString并只使用NSRange 。 那么你的方法可能看起来像这样:

 func convertText(inputText: String) -> NSAttributedString { let attrString = NSMutableAttributedString(string: inputText) let boldFont = UIFont(name: "Helvetica-Bold", size: 14.0)! var r1 = (attrString.string as NSString).rangeOfString("<b>") while r1.location != NSNotFound { let r2 = (attrString.string as NSString).rangeOfString("</b>") if r2.location != NSNotFound && r2.location > r1.location { let r3 = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length) attrString.addAttribute(NSFontAttributeName, value: boldFont, range: r3) attrString.replaceCharactersInRange(r2, withString: "") attrString.replaceCharactersInRange(r1, withString: "") } else { break } r1 = (attrString.string as NSString).rangeOfString("<b>") } return attrString }