在函数外部传递JSON响应

时间:2018-10-21 11:01:32

标签: ios swift uicollectionview swift4

如何将我的JSON响应(datagetStories()函数传递到函数之外的新变量(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: JSON response contains data

如果您正在阅读本文,谢谢。 祝你有美好的一天!

2 个答案:

答案 0 :(得分:0)

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

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

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

CompletionHandler(data.result)

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

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

答案 1 :(得分:0)

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

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()
    })
}