web-dev-qa-db-ja.com

Swiftキーのオブジェクトとしての配列の読み取りと初期化のリスト

私はSwiftで小さなUITableViewベースのアプリを開発しています。私はいくつかの基本的な配列をそのようにハードコーディングすることから始めました(基本的なクラス宣言とUITableViewアウトレット宣言が含まれています:

import UIKit

class ScenesViewController: UITableViewController {

@IBOutlet var myTableView: UITableView

var sceneName = ["Scene 1", "Scene 2", "Scene 3", "Scene 4", "Scene 5"]
var sceneDetail = ["Hi", "Hello", "Bye", "My Bad", "Happy"]

このコードはUITableViewController内にあり、すべてUITableViewに接続されているコンセントがあります。 「Scenes.plist」と呼ばれるこのためのplistを作成し、コードを置き換えようとしました。 Objective-Cでは、次のようにします。

NSString *path = [[NSBundle mainBundle] pathForResource:@"Scenes" ofType:@"plist"];

NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
sceneName = [dict objectForKey:@"SceneName"];
sceneDetail = [dict objectForKey:@"SceneDetail"];

私はこれをSwiftこのように始めました:

let path = NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist")

let dict = NSDictionary(contentsOfFile:path)  // Error: 'ScenesViewController.Type' does not have a member named 'path'

私は解決策を求めてインターネットを調べましたが、解決策を見つけることができませんでした。それで私は次の行動方針を取りました-「ほぼ」ワンライナー:

let dict = NSDictionary(contentsOfFile: 
    NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist"))

var sceneName = dict["SceneName"] // Error: 'ScenesViewController.Type' does not have a member named 'dict'

さて、私がほとんど頼ることができる唯一の解決策は、配列ごとに1行にすべてを配置することです。

var sceneName = NSDictionary(contentsOfFile: 
    NSBundle.mainBundle().pathForResource("Scenes", ofType:"plist").objectForKey("SceneName")
// Warning: Variable 'sceneName' inferred to have type 'AnyObject!', which may be unexpected
// Fix-It: Add an explicit type annotation to silence this warning (var sceneName: AnyObject! = ...)

そこで、エラーが多かったことを確認するために、明示的な型アノテーションを追加しました。 cellForRowAtIndexPath:関数の内部:

override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
    let cell: UITableViewCell = tableView!.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell

    // Configure the cell...

    cell.textLabel.text = sceneName[indexPath!.row] // Error: could not find member 'row'
    return cell
}

実際には2つのエラー;これが誤って複製されているかどうかはわかりません。次のエラーはprepareForSegue:sender:メソッドにあります。

override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
    if segue?.identifier == "ShowDetails" {
        var detailVC: ScenesDetailViewController = segue!.destinationViewController as ScenesDetailViewController

        var myIndexPath: NSIndexPath = myTableView.indexPathForSelectedRow()

        var row: Int = myIndexPath.row

        detailVC.detailModal = [sceneDetail[row], sceneName[row]] // Error: Could not find an overload for 'subscript' that accepts the supplied arguments
    }
}

ここでも、2つのエラーがあります。ただし、これはsceneDetailsceneNameの両方が使用されているためだと思います。 Objective-Cにない(または私が遭遇していない)ファイルのplistを読んだり使用したりすると、いたるところにエラーがあるようです。

13
virenabhyankar

最初の問題を解決するには、次のような関数内にコードを配置します。

var memoryName = []
var memoryDetail = []

override func awakeFromNib() {
    super.awakeFromNib()

    let path = NSBundle.mainBundle().pathForResource("Memories", ofType:"plist")
    let dict = NSDictionary(contentsOfFile:path)

    memoryName = dict["MemoryName"] as Array<String>
    memoryDetail = dict["MemoryDetail"] as Array<String>
}
19
paiv

これを解決するには、オブジェクトの初期化後に呼び出される関数にコードを移動します。

プロパティは、オブジェクトの初期化の一部として初期化されます。パスとdictをプロパティとして作成し、初期化の要件を満たさないコードでそれらを初期化しようとしています。

初期化子は、初期化の最初のフェーズが完了するまで、インスタンスメソッドを呼び出したり、インスタンスプロパティの値を読み取ったり、selfを値として参照したりすることはできません。

-Swiftプログラミング言語-初期化-安全性チェック4

また、sceneNamesceneDetailだけが必要なようですプロパティ。初期化後にsceneDetailとsceneNameを設定するために使用するメソッドのスコープ内で完全に移動できます。

添え字エラーが何であるか正確にを言うのは難しいです。なぜなら、どのタイプのデータdetailVC.detailModalが含まれるべきかわからないからです。それでも、間違ったタイプのオブジェクトがdetailModal配列に渡されているようです。この問題のちょっとした説明は Swift and array

1
timeSmith