将数据传递给函数中的segue.destination

时间:2016-12-23 04:43:10

标签: ios arrays swift swift3 segue

我正在尝试在Segue调用上进行2次API调用,并最终将第二次调用的数据数据传递给CollectionView。通过第一次通话,我得到一个值 catID ,我需要这个值才能拨打另一个电话:

let searchEndpoint: String = MY_ENDPOINT

// Add auth key
let serviceCallWithParams = searchEndpoint + "?PARAMETER"
guard let url = URL(string: serviceCallWithParams) else {
    print("Error: cannot create URL")
    return
}

let urlRequest = URLRequest(url: url)

// setting up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

// making the request
let task = session.dataTask(with: urlRequest) {
    (data, response, error) in
    // error check
    guard error == nil else {
        print("error")
        print(error)
        return
    }
    // make sure we got data
    guard let responseData = data else {
        print("Error: did not receive data")
        return
    }
    // parse JSON
    do {
        guard let catData = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
            print("error converting data to JSON")
            return
        }
        if let data = catData["data"] as? [String: Any] {
            if let array = data["categories"] as? [Any] {
                if let firstObject = array.first as? [String: Any] {
                    if let catId = firstObject["catId"] as? Int {
                        getTitles(catId: catId)
                    }
                }
            }
        }

    } catch  {
        print("error converting data to JSON")
        return
    }
}
task.resume()

然后getTitles函数如下所示:

func getTitles(catId: Int) {
    let catIdString = String(catId)
    let titlesEndPoint: String = MY_ENDPOINT + catIdString
    // Add auth key
    let titlesEndPointWithParams = titlesEndPoint + "?PARAMETER"
    guard let titlesUrl = URL(string: titlesEndPointWithParams) else {
        print("Error: cannot create URL")
        return
    }

    let titlesUrlRequest = URLRequest(url: titlesUrl)

    // set up the session
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    // make the request
    let task = session.dataTask(with: titlesUrlRequest) {
        (data, response, error) in
        // check for any errors
        guard error == nil else {
            print("error calling GET on listCategoryTitles")
            print(error)
            return
        }
        // make sure we got data
        guard let titlesData = data else {
            print("Error: did not receive data")
            return
        }
        // parse the JSON
        do {
            guard let allTitles = try JSONSerialization.jsonObject(with: titlesData, options: []) as? [String: AnyObject] else {
                print("error converting data to JSON")
                return
            }
            if let titlesJson = allTitles["data"] as? [String: Any] {
                if let titlesArray = titlesJson["titles"] as? Array<AnyObject> {
                    self.books = []
                    for (index, value) in titlesArray.enumerated() {
                        var book = Book()
                        book.bookTitle = value["title"] as? String
                        book.bookAuthor = value["author"] as? String
                        if let imageSource = value["_links"] as? Array<AnyObject> {
                            book.bookImageSource = imageSource[1]["href"] as? String
                        }
                        self.books?.append(book)
                    }
                }
            }

        } catch  {
            print("error converting data to JSON")
            return
        }
    }
    task.resume()
}

现在,当我把:

let resultsVC = segue.destination as? CollectionViewController
resultsVC?.books = self.books

外部函数,在目标控制器中我在第一次点击时得到一个空数组作为输出,但在下一个我得到正确的数据。 当我尝试将其置于函数 “getTitles” 时,CollectionViewController中的输出每次都是 “nil” 。 值得一提的是我有 “books” 变量定义如下:

主要控制器:

var books: [Book]? = []

收藏控制器:

var books: [Book]?

我创建了类型[Book],它基本上是在单独的struct中有3个字符串变量的对象。

上面的所有代码都封装在

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowResults" {

非常感谢任何帮助/指南!

1 个答案:

答案 0 :(得分:0)

当你进行api调用时,它将在后台执行,意思是asynchronouslyprepare(for:sender:)将调用synchronously

现在从您的问题看来,您已经在故事板中创建了从ButtonViewController的segue,所以在您从api得到回复之前,您将被移动到目标控制器,以解决您的问题您需要从Source ViewController到Destination ViewController创建segue并设置其标识符。在for循环之后在getTitles(catId: Int)方法内部执行主线程上的segue。

for (index, value) in titlesArray.enumerated() {
    var book = Book()
    book.bookTitle = value["title"] as? String
    book.bookAuthor = value["author"] as? String
    if let imageSource = value["_links"] as? Array<AnyObject> {
        book.bookImageSource = imageSource[1]["href"] as? String
    }
    self.books?.append(book)
}

DispatchQueue.main.async {
    self.performSegue(withIdentifier: "ShowResults", sender: nil)
}

prepare(for:sender:)内进行更改,如下所示。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     if segue.identifier == "ShowResults" {
          let resultsVC = segue.destination as? CollectionViewController
          resultsVC?.books = self.books
     }
}