Search code examples
iosrubyjsonrubymotion

Parsing JSON using RubyMotion


I have a RubyMotion class that reads from Twitter's search API to create Tweet objects as below.

When I run it I get this error:

(main)> 2012-11-08 17:01:32.634 Hello[39940:c07] -[__NSCFString bytes]: unrecognized selector sent to instance 0xea1f800
2012-11-08 17:01:32.685 Hello[39940:c07] json.rb:20:in `parse:': NSInvalidArgumentException: -[__NSCFString bytes]: unrecognized selector sent to instance 0xea1f800 (RuntimeError)
    from tweets_controller.rb:11:in `create_tweets'
    from tweets_controller.rb:7:in `tweets'
    from twitter_view_controller.rb:21:in `tableView:numberOfRowsInSection:'
    from app_delegate.rb:10:in `application:didFinishLaunchingWithOptions:'
2012-11-08 17:01:32.686 Hello[39940:c07] *** Terminating app due to uncaught exception 'RuntimeError', reason: 'json.rb:20:in `parse:': NSInvalidArgumentException: -[__NSCFString bytes]: unrecognized selector sent to instance 0xea1f800 (RuntimeError)
    from tweets_controller.rb:11:in `create_tweets'
    from tweets_controller.rb:7:in `tweets'
    from twitter_view_controller.rb:21:in `tableView:numberOfRowsInSection:'
    from app_delegate.rb:10:in `application:didFinishLaunchingWithOptions:'

How should I parse the JSON?

class TweetsController
  def initialize
    @twitter_accounts = %w(dhh google)
  end

  def tweets
    @tweets ||= create_tweets
  end

  def create_tweets
    BW::JSON.parse(twitter_search_results)["results"].each do |result|
      @tweets << Tweet.new(result)
    end
    @tweets
  end

  def twitter_search_results
    query = @twitter_accounts.map{ |account| "from:#{account}" }.join(" OR ")
    url_string = "http://search.twitter.com/search.json?q=#{query}"
    url_string_escaped = url_string.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    url = NSURL.URLWithString(url_string_escaped)
    request = NSURLRequest.requestWithURL(url)
    response = nil
    error = nil
    data = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error: error)
    ##raise "BOOM!" unless (data.length > 0 && error.nil?)
    json = NSString.alloc.initWithData(data, encoding: NSUTF8StringEncoding)
  end
end

class Tweet
  attr_reader :created_at, :from_user, :text
  def initialize(tweet_result)
    @created_at = tweet_result["created_at"]
    @from_user = tweet_result["from_user"]
    @text = tweet_result["text"]
  end
end

Solution

  • Short answer: skip using Bubblewrap.

      def create_tweets
        json_string = twitter_search_results.dataUsingEncoding(NSUTF8StringEncoding)
        e = Pointer.new(:object)
        json_hash = NSJSONSerialization.JSONObjectWithData(json_string, options:0, error: e)
        json_hash["results"].each do |result|
          @tweets << Tweet.new(result)
        end
      end