我正在关注斯坦福大学的cs193P“快速开发IOS 9应用程序”课程。我正在完成讲座的第4课。该应用程序从Twitter获取推文,其中包括您搜索的单词。 我尝试改变以特殊字符(@,#或http)开头的单词的颜色。
当我编译应用程序时,它成功地改变颜色,应用程序运行没有问题。但是当我向下滚动并且我的应用程序试图显示新推文时,它会崩溃,从而产生以下错误。
由于未捕获的异常'NSRangeException'而终止应用程序,原因:'NSMutableRLEArray objectAtIndex:effectiveRange :: out of bounds'
我正在使用Xcode 7.3.1和swift 2.2
我在Stackoverflow和谷歌上搜索过,发现了以下类似的问题 Question-1 Question-2 Question-3 Question-4
在上述问题中,问题与范围的长度或滥用NSRange的长度有关。
在我的情况下,我没有看到任何与长度相关的问题。您可以click在Github中查看我的整个项目
public class Mention: NSObject
{
public var keyword: String // will include # or @ or http prefix
public var nsrange: NSRange // index into an NS[Attributed]String made from the Tweet's text
public override var description: String { return "\(keyword) (\(nsrange.location), \(nsrange.location+nsrange.length-1))" }
init?(fromTwitterData data: NSDictionary?, inText text: NSString, withPrefix prefix: String)
{
guard
let indices = data?.valueForKeyPath(Tweet.TwitterKey.Entities.Indices) as? NSArray,
let start = (indices.firstObject as? NSNumber)?.integerValue where start >= 0,
let end = (indices.lastObject as? NSNumber)?.integerValue where end > start
else {
return nil
}
var prefixAloneOrPrefixedMention = prefix
if let mention = data?.valueForKeyPath(Tweet.TwitterKey.Entities.Text) as? String {
prefixAloneOrPrefixedMention = mention.prependPrefixIfAbsent(prefix)
}
let expectedRange = NSRange(location: start, length: end - start)
guard
let nsrange = text.rangeOfSubstringWithPrefix(prefixAloneOrPrefixedMention, expectedRange: expectedRange)
else {
return nil
}
self.keyword = text.substringWithRange(nsrange)
self.nsrange = nsrange
} }
可以看出,开始总是大于结束。这就是为什么在expectRange长度(这是结束开始)永远不会是负数。
最后导致崩溃的代码如下(以“tweetTextLabel?.attributedText”开头的行导致崩溃)
class TweetTableViewCell: UITableViewCell
{
@IBOutlet weak var tweetScreenNameLabel: UILabel!
@IBOutlet weak var tweetTextLabel: UILabel!
@IBOutlet weak var tweetProfileImageView: UIImageView!
@IBOutlet weak var tweetCreatedLabel: UILabel!
var tweet: Twitter.Tweet? {
didSet {
updateUI()
}
}
var mentionsList = [Array<Mention>]()
private func updateUI()
{
// reset any existing tweet information
tweetTextLabel?.attributedText = nil
tweetScreenNameLabel?.text = nil
tweetProfileImageView?.image = nil
tweetCreatedLabel?.text = nil
// load new information from our tweet (if any)
if let tweet = self.tweet
{
tweetTextLabel?.text = tweet.text
if tweetTextLabel?.text != nil {
for _ in tweet.media {
tweetTextLabel.text! += " "
}
}
mentionsList.append(tweet.hashtags)
mentionsList.append(tweet.urls)
mentionsList.append(tweet.userMentions)
var mentionColor = UIColor.clearColor()
for mentions in mentionsList {
switch mentions {
case _ where mentions == tweet.hashtags:
mentionColor = UIColor.blueColor()
case _ where mentions == tweet.urls:
mentionColor = UIColor.redColor()
case _ where mentions == tweet.userMentions:
mentionColor = UIColor.brownColor()
default: break
}
for mention in mentions {
(tweetTextLabel?.attributedText as? NSMutableAttributedString)?.addAttribute(
NSForegroundColorAttributeName, value: mentionColor, range: mention.nsrange) // Causes the crash
}
}
tweetScreenNameLabel?.text = "\(tweet.user)" // tweet.user.description
if let profileImageURL = tweet.user.profileImageURL {
if let imageData = NSData(contentsOfURL: profileImageURL) { // blocks main thread!
tweetProfileImageView?.image = UIImage(data: imageData)
}
}
let formatter = NSDateFormatter()
if NSDate().timeIntervalSinceDate(tweet.created) > 24*60*60 {
formatter.dateStyle = NSDateFormatterStyle.ShortStyle
} else {
formatter.timeStyle = NSDateFormatterStyle.ShortStyle
}
tweetCreatedLabel?.text = formatter.stringFromDate(tweet.created)
}
}
}
请帮帮我。我已经在这个问题上工作了好几天,找不到错误的地方。也许是因为一些特殊字符,字符串中的字符数更多。但我不知道如何解决这个问题。