在swift 2中使用addAttribute时出现NSRangeException错误

时间:2016-10-08 20:52:12

标签: ios swift twitter xcode7

我正在关注斯坦福大学的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)
        }
    }
}

请帮帮我。我已经在这个问题上工作了好几天,找不到错误的地方。也许是因为一些特殊字符,字符串中的字符数更多。但我不知道如何解决这个问题。

0 个答案:

没有答案