2016-05-22 38 views
1

美好的一天給大家。首先我想告訴你,我在編程方面一般都很新。因此,如果我沒有任何意義,我想向前道歉。我爲iOS Swift做了一個bootcamp,但是沒有包含Rest或解析JSON。我現在試圖教自己做所有我能找到的教程。我知道有Alamofire使它更容易,但我想學習如何使用NSURLSession首先做到這一點。我找到了一個用老版本的Swift編寫的教程,現在我已經被困了好幾天了。我嘗試了所有可以在Google和Google上找到的選項。但我仍然不明白我做錯了什麼。這是我的代碼;並在其下面描述了我認爲問題發生的地方。 在此先感謝您的幫助。無法弄清楚如何在Swift中使用NSURLSession將jsonData加載到NSDictionary中

import Foundation 
import UIKit 

class FlickrHelper: NSObject { 

class func UrlForSearchString(searchString: String) -> String { 
    let apiKey:String = "733e5b6f446812afdec3c021454dd9bb" 
    let search:String = searchString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! 
    return "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=\(apiKey)&text=\(search)&per_page=20&format=json&njsoncallback=1" 

} 
class func UrlForFlickrPhoto(photo:FlickrPhoto, size:String) -> String { 
    var _size = size 
    if _size.isEmpty { 
     _size = "m" 
    } 
    return "http://farm.\(photo.farm).staticflickr.com/\(photo.photoID)_\(photo.secret)_\(_size).jpg" 
} 

func searchFlickrForString(searchStr:String, completion:(searchString:String!, flickrPhotos:NSMutableArray!, error:NSError!) ->()) { 

    let searchUrl:String = FlickrHelper.UrlForSearchString(searchStr) 
    let queue:dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

    dispatch_async(queue, { 

     var error:NSError? 

     let searchResultString:String! = try! String(contentsOfURL: NSURL(string: searchUrl)!, encoding: NSUTF8StringEncoding) 

     if error != nil { 
      completion(searchString: searchStr, flickrPhotos: nil, error: error) 
     } else { 
      // Parse json response. 

      let jsonData:NSData! = searchResultString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) 

      let resultDict = try? NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String:AnyObject] as NSDictionary 

      let status:String = resultDict?.objectForKey("stat") as! String 

      if status == "fail" { 
       let stError:NSError? = NSError(domain: "FlickrSearch", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:(resultDict?.objectForKey("message"))!]) 

       completion(searchString: searchStr, flickrPhotos: nil, error: stError) 
      } else { 
       let resultArray:NSArray = (resultDict?.objectForKey("photos")?.objectForKey("photo"))! as! NSArray 

       let flickrPhotos:NSMutableArray = NSMutableArray() 

       for photoObject in resultArray { 
        let photoDict:NSDictionary = photoObject as! NSDictionary 

        var flickrPhoto:FlickrPhoto = FlickrPhoto() 
        flickrPhoto.farm = photoDict.objectForKey("farm") as! Int 
        flickrPhoto.server = photoDict.objectForKey("server") as! String 
        flickrPhoto.secret = photoDict.objectForKey("secret") as! String 
        flickrPhoto.photoID = photoDict.objectForKey("id") as! String 

        let searchURL:String = FlickrHelper.UrlForFlickrPhoto(flickrPhoto, size: "m") 
        do { 
        let imageData:NSData = try NSData(contentsOfURL: NSURL(string: searchURL)!, options: NSDataReadingOptions()) 

         let image:UIImage = UIImage(data:imageData)! 

         flickrPhoto.thumbnail = image 

         flickrPhotos.addObject(flickrPhoto) 

        } catch { 
         print(error) 
        } 

        completion(searchString: searchStr, flickrPhotos: flickrPhotos, error: nil) 

       } 
      } 
     } 
    }) 
    } 
} 

我收到jsonData,但它沒有將其分配給我的resultDict。我的結果是零。在我的項目崩潰的線是這個:

let status:String = resultDict?.objectForKey("stat") as! String 

但我猜問題是在這一行:

let resultDict = try? NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String:AnyObject] as NSDictionary 
+0

避免使用強制展開或隱含展開自選儘可能。基本上使用'!'運算符。您需要實際檢查一次演員是否成功,或者您可以將自己設置爲在某處發生運行時崩潰。 [Documentation here](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID330) – ColGraff

+0

非常感謝爲反饋。我實際上試圖讓它工作第一,然後我會清理它,如果讓我們嘗試,做,趕上。這將是我的下一個練習:-)。 – FredFlinstone

+0

我明白你想自己做這件事來學習。但是我建議使用SwiftlyJson來控制JSON反序列化。這削減了很多可選的鏈接,你最終不得不這樣做。這仍然使用你的網絡電話等,它只是使JSON的解析更愉快。你可以在這裏找到它:https://github.com/SwiftyJSON/SwiftyJSON – totiG

回答

0

試試這個。

不是傳遞空數組到NSJSONSerialization.JSONObjectWithData的,使用帶片段類型的允許,如下所示:

let resultDict = try? NSJSONSerialization.JSONObjectWithData(jsonData, NSJSONReadingOptions.AllowFragments) 

這可能解決這個問題。否則,嘗試一些其他選項。


另一種方法可能是這樣的。

  let json = try! NSJSONSerialization.JSONObjectWithData(json!, options: .AllowFragments) 
      print("=====") 
      if let item = json.objectForKey("prices") as! NSArray? { 
       self.uberPriceField.text = item[0].objectForKey("estimate") as? String 
      } 

我在自己的代碼中使用了這個,因爲返回的JSON實際上只是頂層數組。也許它也適用於你。

+0

謝謝,不幸的是,這也是我已經嘗試過的:-(。 – FredFlinstone

+0

謝謝,即使我非常確定我的JSON是一個字典(它以{開頭)我確實嘗試了你的建議。不幸的是,工作。 – FredFlinstone

0

以下是我用我凸出的代碼,是指相同的,讓我知道如果仍然問題仍然存在: -

let requestURL: NSURL = NSURL(string: "(Ur URL)/get_SearchList.php?cth=\(cth),\(kwValue)")! 
     let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL) 
     let session = NSURLSession.sharedSession() 
     let task = session.dataTaskWithRequest(urlRequest) { 
      (data, response, error) -> Void in 

      let httpResponse = response as! NSHTTPURLResponse 
      let statusCode = httpResponse.statusCode 

      if (statusCode == 200) { 

       do{ 

        let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) 



        if let products = json["product"] as? [[String: AnyObject]] { 
         dispatch_async(dispatch_get_main_queue(), { 
         for product in products { 

           if let cth = product["cth"] as? String { 


            if let name = product["productname"] as? String { 
             self.cthArray.append(cth); 
             self.prodArray.append(name); 


            } 

           } 


         }//for loop 
          dispatch_async(dispatch_get_main_queue(),{ 
           self.tableView.reloadData() 
          }) 
         }) 

        }// if loop 

       } 
       catch 
       { 
        print("Error with Json: \(error)") 

       } 

      } 
      else 
      { 
       // No internet connection 
       // Alert view controller 
       // Alert action style default 


      } 

     } 

     task.resume() 
相關問題