在函数内将数据传递给 segue.destination 的问题
Posted
技术标签:
【中文标题】在函数内将数据传递给 segue.destination 的问题【英文标题】:issue passing data to segue.destination within function 【发布时间】:2016-12-23 04:43:10 【问题描述】:我正在尝试对 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],它基本上是在单独的结构中具有 3 个字符串变量的对象。
以上所有代码都封装在
中override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "ShowResults"
任何帮助/指南将不胜感激!
【问题讨论】:
当你写 self.performSegueWithIdentifier("ShowResults", sender: nil) ??添加调用Segue的代码。 您的 API 调用将异步完成,因此您需要从完成闭包执行您的 segue 【参考方案1】:当您进行 api 调用时,它将在后台执行意味着 asynchronously
其中 prepare(for:sender:)
将调用 synchronously
。
现在从您的问题来看,您似乎在情节提要中创建了从 Button
到 ViewController
的 segue,因此在您从 api 获得响应之前,您将被移动到目标控制器,以解决您需要解决的问题从 Source
ViewController 创建 segue 到 Destination
ViewController 并设置其标识符。在你的 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
【讨论】:
以上是关于在函数内将数据传递给 segue.destination 的问题的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 如何将数据传递给 ObservedObject 函数