cs193p – Project #4 Assignment #4 Task #1

By SharkD (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0) or GFDL (http://www.gnu.org/copyleft/fdl.html)], via Wikimedia Commons

Please note, this blog entry is from a previous course. You might want to check out the current one.

Enhance Smashtag from lecture to highlight (in a different color for each) hashtags, urls and user screen names mentioned in the text of a Tweet (these are known as “mentions”). Note that mentions are already located for you in each Tweet by Twitter and show up as [IndexedKeyword]s in the Tweet class in the supplied Twitter code.

The tweet class provides nearly everything needed – arrays of indexed keywords. What’s left is to choose a color for the keyword type – as public properties of the cell view:

    var hashtagColor = UIColor.blueColor()
    var urlColor = UIColor.redColor()
    var userMentionsColor = UIColor.greenColor()


An extension of the mutable string class takes an array of indexed key words and a color, loops over the array and adds the foreground color to the range containing the key word:

private extension NSMutableAttributedString {
    func changeKeywordsColor(keywords: [Tweet.IndexedKeyword], color: UIColor) {
        for keyword in keywords {
            addAttribute(NSForegroundColorAttributeName, value: color, range: keyword.nsrange)
        }
    }
}

Add the media icons to the text – if there are any. Create an mutable attributed string and use the extension to set the color for the keywords. Finally, use the string form the text view:

    func updateUI() {
        ...
            var text = tweet.text
            
            for _ in tweet.media {
                text += " x" // the icon was not printable here
            }            
            var attributedText = NSMutableAttributedString(string: text)
            attributedText.changeKeywordsColor(tweet.hashtags, color: hashtagColor)
            attributedText.changeKeywordsColor(tweet.urls, color: urlColor)
            attributedText.changeKeywordsColor(tweet.userMentions, color: userMentionsColor)            
            tweetTextLabel?.attributedText = attributedText            
            ...
    }

One tiny blemish is that the media URLs are not part of the URLs array and the media array does not contain indexed keywords, therefore they are not colored …

A quick and dirty hack – it is not really proper coding to change third-party code directly – is to adjust the tweet class.

Add a public property to hold the indexed media URLs and fill them in the initializer:

    public let mediaMentions = [IndexedKeyword]()
    init?(data: NSDictionary?) {
        ...
                    if let mediaEntities = data?.valueForKeyPath(TwitterKey.Media) as? NSArray {
                        ...
                        mediaMentions = getIndexedKeywords(mediaEntities, inText: text, prefix: "h")
                    }
                    ...
    }

Now it is possible to colorize also the media URLs:

    func updateUI() {
        ...
            attributedText.changeKeywordsColor(tweet.mediaMentions, color: urlColor)            
            ...
    }

The complete code for task #1 is available on GitHub.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

17 thoughts on “cs193p – Project #4 Assignment #4 Task #1”

  1. You are over-complicating it. It’s just a matter of changing attributes in the TwitterTableViewCell updateUI() function:

    replace
    tweetTextLabel?.text = tweet.text
    by :

    var attributedText = NSMutableAttributedString(string: tweet.text)
    for hashtag in tweet.hashtags {
    attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.brownColor(), range: hashtag.nsrange)
    }
    for url in tweet.urls {
    attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: url.nsrange)
    }
    for userMention in tweet.userMentions {
    attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.greenColor(), range: userMention.nsrange)
    }

    tweetTextLabel?.attributedText = attributedText

    1. Writing three times the same code, with different variables, that’s a candidate for using a common method …
      … and providing the means to change colors in a public API is also not too bad, is it?

      You might also want to take a look at hint #8 😉

      … and your code has an unintended side effect. In the code from the lecture, media icons are added to the text label after the text label has been set. If you replace only the code above, you will notice that tweets with media links will not be colorized, as adding the icon to the text, will remove the attributes …

      1. I agree, it can be simplified and colors can be made public. That was just an example to show you that you should not touch the Tweet class and everything you have to do lies in the TweetTableViewCell …

          1. I really liked the use of extensions in this problem. I confess I avoided at first but realised this was the simplest way. Well done Martin!

  2. More of a question than a comment. Did you start with the downloadable version of Smashtag, or start from scratch? The instructions seem to indicate that was the intent (“Enhance Smashtag from lecture to highlight”).

      1. Thanks for the reply, I think I will do the same, rather than start with the project file that is provided.

  3. Hi Martin,

    Could you explain why optional chaining is used (with ?) if all @IBOutlets in TweetTableViewCell class are implicitly unwrapped?

    For example:
    tweetTextLabel?.attributedText = attributedText

  4. Hi Martin
    I now turn to Smashtag and the stanford twitter is not working.
    Could you please tell how to change it to log to regulate twitter and how to log in to own twitter account.
    I don’t know what to do.
    Please help

  5. Hi Martin

    Thank you for your answer, I found it!!

    By the way could you solve snapshot problem for me?
    The code is in Project #3 Assignment #3 Extra Task #2 page…

    I cannot find the answer for that

Leave a Reply

Your email address will not be published.