在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
。 点击就会导致_NSRange
types别名的信息,而这个信息又有两个名为location
和length
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) NSString
。 String
方法返回一个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 }