2012-11-08 85 views
2

我有一個RubyMotion類,它從Twitter的搜索API讀取以創建如下的對象Tweet使用RubyMotion解析JSON

當我運行它,我得到這個錯誤:

(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:' 

我應該如何解析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 

回答

1

簡短的回答:採用氣泡布跳過。

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 
+0

我接受了我自己的答案,因爲它最簡潔地回答我的問題。史蒂夫羅斯的回答和博客文章非常出色,值得一讀:http://sxross-blog.herokuapp.com/2012/11/11/how-to-build-a-twitter-search-client-in-ruby -運動/ – Mike

3

有幾個CocoaPods可以解決這個問題。特別是JSONKit。

編輯:這不是一個bubblewrap錯誤。這是解釋Twitter的迴應的問題。我有一個用bubblewrap和JSONKit這樣做的示例。我很快就會把它放在GitHub上。簡短的總結,Twitter返回一個數組數組。第一個元素是該組中的內容,第二個元素是實際數據。你想迭代最外層的數組尋找一個數組,其第一個元素是結果,然後使用第二個元素來派生你的響應數據。這裏有兩個可供選擇的實現:

def create_tweets_using_bubblewrap 
    @twitter_accounts = %w(dhh google) 
    query = @twitter_accounts.map{ |account| "from:#{account}" }.join(" OR ") 
    url_string = "http://search.twitter.com/search.json?q=#{query}" 

    BW::HTTP.get(url_string) do |response| 
    parsed = BW::JSON.parse response.body.to_str 
    parsed.each do |item| 
     next if item[0] != 'results' 
     @feed = [] 
     item[1].each do |tweet| 
     @feed << {:from => tweet['from_user'], :text => tweet['text']} 
     end 
    end 
    end 
    @feed 
end 

def create_tweets_using_jsonkit 
    @twitter_accounts = %w(dhh google) 
    query = @twitter_accounts.map{ |account| "from:#{account}" }.join(" OR ") 
    url_string = "http://search.twitter.com/search.json?q=#{query}" 

    error_ptr = Pointer.new(:object) 
    BW::HTTP.get(url_string) do |response| 
    parsed = response.body.to_str.objectFromJSONStringWithParseOptions JKParseOptionValidFlags, error: error_ptr 
    if parsed.nil? 
     error = error_ptr[0] 
     puts error.userInfo[NSLocalizedDescriptionKey] 
     @timer.setValid false 
    else 
     parsed.each do |item| 
     next if item[0] != 'results' 
     @feed = [] 
     item[1].each do |tweet| 
      @feed << {:from => tweet['from_user'], :text => tweet['text']} 
     end 
     end 
    end 
    end 
    @feed 
end 

http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html

+0

感謝您的支持以及您在http://sxross-blog.herokuapp.com/2012/11/11/how-to-build-a-twitter-search-client-in-ruby-議案/ – Mike