【问题标题】:Pass JSON response outside of the function [duplicate]在函数之外传递 JSON 响应 [重复]
【发布时间】:2019-03-25 15:47:22
【问题描述】:

如何将我的 JSON 响应 (data) 从 getStories() 函数传递到我的函数之外的新变量 (var stories),然后才能将该新变量用于我的 CollectionViewController ?

这是我的代码:

import UIKit

class StoryCollectionViewController: UICollectionViewController {

    // MARK: - ***** Properties *****
    private var stories: Story!

    // MARK: - ***** Life Cycles *****
    override func viewDidLoad() {
        super.viewDidLoad()

        // Register cell class
        collectionView?.register(UINib.init(nibName: "StoryCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: Constants.reuseIdentifier)

        // Get Stories
        getStories()

        print(stories.storyID) // Here should return 15 but return NIL and I don't know why
    }

    // MARK: ***** UICollectionView DataSource Methods *****
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.reuseIdentifier, for: indexPath) as! StoryCollectionViewCell

        DispatchQueue.main.async {
            //cell.storyImageView.imageFromServerURL(urlString: self.posterUrl)
            //cell.storyNameLabel.text = self.stories?.name
        }

        return cell
    }

    //MARK: - ***** CollectionView Delegate Methods *****
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "showStoryDetails", sender: self.stories)
    }

    // Get Stories from Amazon API server
    func getStories(){

        Spinner.show("Loading Stories")

        let defaultSession = URLSession(configuration: .default)

        if let urlComponents = URLComponents(string: Constants.baseURL) {

            guard let url = urlComponents.url else { return }

            let dataTask = defaultSession.dataTask(with: url) { (data, _, error) in

                if error != nil {

                    self.showMessage(message: error.debugDescription)
                } else if let data = data {

                    do {
                        let data = try JSONDecoder().decode(ModelJson.self, from: data)

                        self.stories = data.result // This object "stories" is empty outside of this function ..........

                        print("Story ID: \(self.stories.storyID!)") // Here return 15 which is correct
                    } catch {
                        self.showMessage(message: error.localizedDescription)
                    }
                }
                Spinner.hide()
            }
            dataTask.resume()
        }
    }
}

这是一个屏幕,显示我的 JSON 响应包含数据并在控制台中返回 15:

感谢各位阅读本文。 祝你有美好的一天!

【问题讨论】:

  • 代码运行良好且异步。删除viewDidLoad 中的print 行,并在working print 行之后或代替working 行执行您想要在完成处理程序中执行的操作。并且不要忘记在主线程上重新加载集合视图。为什么集合视图是可选的?
  • 修改函数以获取完成处理程序:func getStories(completion: (Story) -> Void)

标签: ios swift uicollectionview swift4


【解决方案1】:

您可以像这样在 getStories 函数中使用闭包:

func getStories(CompletionHandler: @escaping (Story)->()) {
     // 
}

在数据被调用后,像这样调用这个闭包:

CompletionHandler(data.result)

然后,当调用此方法时,您可以在闭包内处理您的对象并根据需要更新您的控制器。

getStories { [weak self] (stories) in
    self?.stories = stories
}

【讨论】:

    【解决方案2】:

    getStories 方法包含。异步操作。这意味着您不会立即得到响应。调用getStories 方法后无法获取故事。在设置 stories 属性后执行此操作。示例:

    func getStories(completion: @escaping () -> Void) {
        Spinner.show("Loading Stories")
    
        let defaultSession = URLSession(configuration: .default)
    
        if let urlComponents = URLComponents(string: Constants.baseURL) {
            guard let url = urlComponents.url else { return }
    
            let dataTask = defaultSession.dataTask(with: url) { (data, _, error) in
                if error != nil {
    
                    self.showMessage(message: error.debugDescription)
                } else if let data = data {
                    do {
                        let data = try JSONDecoder().decode(ModelJson.self, from: data)
    
                        self.stories = data.result
                    } catch {
                        self.showMessage(message: error.localizedDescription)
                    }
                }
                Spinner.hide()
                completion()
            }
            dataTask.resume()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getStories(completion: { [weak self] in
            self?.collectionView.reloadData()
        })
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-15
      • 1970-01-01
      • 2012-03-06
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多