在函数内将数据传递给 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

现在从您的问题来看,您似乎在情节提要中创建了从 ButtonViewController 的 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 函数

collectionView 函数 didSelectItemAt indexPath 将数据传递给下一个视图控制器

如何将数据传递给另一个视图函数进行处理

Vue:将数据传递给动态组件

在将数据传递给类构造函数之前,先在Python中预处理数据

mapStateToProps 将数据传递给道具