swiftのラップ、アンラップについての質問です

以下のソースコードで
---------------------------------------------------------------------------------

// ニュース一覧データを格納する配列
var newsDataArray = NSArray()

override func viewDidLoad() {
super.viewDidLoad()

// Webサーバーに対してHTTP通信のリクエストを出してニュース記事データを取得
let requestUrl = "https://ajax.googleapis.com/ajax/services/search/news?v=1.0&topic=p&hl=ja&rsz=8"
Alamofire.request(.GET, requestUrl).responseJSON {
(request, response, json, error) in
//println(json)
// 取得したニュース記事データをテーブルビューに表示
// jsonデータをNSDictionary型に変換
let jsonDic = json as! NSDictionary
// 辞書化したjsonDicからresponseDataを取り出す
let responseData = jsonDic["responseData"] as! NSDictionary
// resultsを取り出す
self.newsDataArray = responseData["results"] as! NSArray
println("\(self.newsDataArray)")
---------------------------------------------------------------------------------

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2015/05/26 07:40:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。
id:yayayai

最後の2行に as! NSDictionary と as! NSArray とキャストしている箇所があります。

このasのアンラップの”!”についてご質問です。

1. as?ではだめで、as!でないといけない理由が不明(as?だとエラーになります)

 →!の場合は、nilになりえないことを表しているのかと思いますが、

  上記コードのjsonレスポンス取得先のサーバーが落ちていたりすると、

  nilになりえる可能性はないのでしょうか。そういうことが無い仕様のため

!ということでしょうか。

お手数ですがよろしくお願い致します。

回答1件)

id:a-kuma3 No.1

回答回数4973ベストアンサー獲得回数2154

ポイント100pt

as?ではだめで、as!でないといけない理由が不明(as?だとエラーになります)

それは、代入先の変数がオプショナルで宣言されていないからです。
なので、式の結果として nil になるものを代入できません。

var newsDataArray = NSArray()       // ★オプショナル型じゃない
    ...
self.newsDataArray = responseData["results"] as! NSArray

いや、この部分だけの話ではないかな。
responseJSON で呼ばれるクロージャの第三引数は AnyObject? です。
しょっぱなでアンラップされているので、それ以降の中身を取り出していくキャストでも as! を使わなければいけなくなります。

// jsonデータをNSDictionary型に変換
let jsonDic = json as! NSDictionary

こうやったら as? でダウンキャストできると思います。

// ニュース一覧データを格納する配列
var newsDataArray:NSArray?      // ★オプショナルで宣言 

override func viewDidLoad() {
  super.viewDidLoad()

  // Webサーバーに対してHTTP通信のリクエストを出してニュース記事データを取得
  let requestUrl = "https://ajax.googleapis.com/ajax/services/search/news?v=1.0&topic=p&hl=ja&rsz=8"
  Alamofire.request(.GET, requestUrl).responseJSON {
    (request, response, json, error) in
      //println(json)
      // 取得したニュース記事データをテーブルビューに表示
      // jsonデータをNSDictionary型に変換
      let jsonDic = json as? NSDictionary     // ★ as?
      // 辞書化したjsonDicからresponseDataを取り出す
      let responseData = jsonDic["responseData"] as? NSDictionary     // ★ as?
      // resultsを取り出す
      self.newsDataArray = responseData["results"] as? NSArray        // ★ as?
      println("\(self.newsDataArray)")


  上記コードのjsonレスポンス取得先のサーバーが落ちていたりすると、
  nilになりえる可能性はないのでしょうか。そういうことが無い仕様のため
!ということでしょうか。

もう、答えは出ていると思いますが、Alamofire を response に nil が入らないようにオプショナルで宣言しないように作る(設計する)ことも可能です。
空の配列を response で渡して、エラーの判定は第4引数で判断するように、とか。
ただし、ダウンキャストの場合は、そのクラスにあってないとキャストの結果が nil になるので、データを取り出すときに nil になる考慮は必要です。


responseJSON に渡すクロージャの引数は、こちらを参照に。completionHandler です。
https://github.com/Alamofire/Alamofire/blob/master/Source/ResponseSerialization.swift#L99


responseJSON から response を取り出すときに、一気にキャストしている例がありました。
http://qiita.com/takecian/items/48422dd2076582b6a6be

  Alamofire.request(.GET, "http://sample.me/api/v1/product", parameters: nil)
    .responseJSON {(_, _, JSON, error) in
      if let productParamArray = JSON as? Array<Dictionary<String,AnyObject>> {
        for productParam in productParamArray {
          let product = Product(name: productParam["name"] as String,

JSON オブジェクトの階層が固定になっちゃいますが、形が分かっているときには便利かもしれません。

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません