简体   繁体   English

Swift URLSession在制作PageView之前不起作用

[英]Swift URLSession not working before making PageView

I have read this post , but I couldn't solve my problem. 我已经阅读了这篇文章 ,但无法解决我的问题。
DispatchQueue.main.async code cannot work to my code. DispatchQueue.main.async代码无法对我的代码起作用。
I think my problem is a little bit different from that. 我认为我的问题与此有所不同。 So I post my question. 所以我发表了我的问题。

I have 3 views. 我有3个意见。

在此处输入图片说明

FirstView is a table view that user can select their choice. FirstView是一个表视图,用户可以选择自己的选择。
SecondView is a view that handles UIPageViewControllerDelegate and DataSource . SecondView是处理UIPageViewControllerDelegateDataSource的视图。
ThirdView is a view which will be page views of Second view . ThirdView是一个视图,它将是Second view页面Second view
(The view at the bottom is PageViewController ) (底部的视图是PageViewController

When user selects and tap the button on the First View , it goes to the Second view . 当用户选择并点击“ First View上的按钮时,它将转到Second view
Then, Second View presents the result. 然后, Second View呈现结果。 (Actually, Third View shows the result, but it seems to be just shown in the Second View .) (实际上,“ Third View显示了结果,但似乎仅在“ Second View 。)

The contents of the result are from the DB on server based on user's selection in the FirstView . 结果的内容基于用户在FirstView的选择来自服务器上的FirstView

I thought that I need to fetched the result from server in the SecondView before presenting results on the ThirdView . 我想,我需要从服务器获取的结果SecondView上呈现结果之前ThirdView

So I write the fetching code on the viewDidLoad in the SecondView 's View Controller . 因此,我在SecondViewView ControllerviewDidLoad上编写了获取代码。

Here's the data model code 这是数据模型代码

struct MyData: Decodable {
let a: String
let b: String
let c: String
}

Here's the Second View class code 这是Second View类代码

class SecondView: UIViewController, UIPageViewControllerDelegate, 
UIPageViewControllerDataSource {

var pageViewController: UIPageViewController!
let pageControl: UIPageControl = UIPageControl()
let pageControlHeight: CGFloat = 20

var passedFromFirstVC: [String] = []
var pageTitle: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()

    var request = URLRequest(url: NSURL(string: "http://xxxxx.xxx/" )! as URL)
    request.httpMethod = "POST"
    var postString = "xxxxxx"
    request.httpBody = postString.data(using: String.Encoding.utf8)

    let task = URLSession.shared.dataTask(with: request) {
        (data, response, error) in

        if error != nil {
            return
        }

        guard let data = data else { return }

        do {
            let fetchedData = try JSONDecoder().decode([MyData].self, from: data)
            print(fetchedData)
            self.pageTitle.append(fetchedData[x].xx)

         } catch let jsonErr {
                print("Error serializing json:", jsonErr)
         }
    }
    task.resume()

And in viewDidLoad code, the pageViewController codes are there. viewDidLoad代码中,存在pageViewController代码。
Here's the residual codes in viewDidLoad . 这是viewDidLoad的剩余代码。

    self.pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "pageviewcontroller") as! UIPageViewController
    self.pageViewController.delegate = self
    self.pageViewController.dataSource = self
    self.pageViewController.view.frame = CGRect(x: 0, y: 65, width: view.frame.width, height: view.frame.height)
    let startVC = self.viewControllerAtIndex(index: 0) as! ContentViewController
    let viewControllers = NSArray(object: startVC)
    self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: true, completion: nil)
    self.addChildViewController(self.pageViewController)
    self.view.addSubview(self.pageViewController.view)
    self.pageViewController.didMove(toParentViewController: self)
}

And to make page index, this code is followed. 为了使页面索引,请遵循以下代码。 Here's the code. 这是代码。

func viewControllerAtIndex(index: Int) -> ContentViewController {

    let vc: ContentViewController = self.storyboard?.instantiateViewController(withIdentifier: "ContentViewController") as! ContentViewController

    vc.pageIndex = index
    print("page just has been moved...")
    print(pageTitles)

    vc.titleText = pageTitles[index]
    return vc
}

But, when I run the app, it stops vc.titleText = pageTitles[index] in this code. 但是,当我运行该应用程序时,它将在此代码中停止vc.titleText = pageTitles[index]
Because, pageTitles are nil. 因为, pageTitles为零。

So I set a breakpoint on the viewDidLoad , and I found that task had not been compiled. 因此,我在viewDidLoad上设置了一个断点,发现该task尚未编译。

It ignores task and task.resume() code, and then complies the following codes. 它忽略tasktask.resume()代码,然后遵循以下代码。

So, DispatchQueue.main.async code cannot work to my code. 因此, DispatchQueue.main.async代码无法对我的代码起作用。

But, when I set certain initial value in pageTitle (even after task.resume() ), then task had been compiled after compiling codes related to other PageViewController . 但是,当我在pageTitle设置某个初始值时(甚至在task.resume() ),则task是在编译与其他PageViewController相关的代码之后编译的。

And, when I made this code in another project with a just single ViewController (not like my PageViewController ), it also compiles task code in viewDidLoad . 而且,当我仅使用一个ViewController在另一个项目中创建此代码时(不同于我的PageViewController ),它也会在viewDidLoad编译task代码。

Why task code in this question had not been compiled? 为什么这个问题中的task代码尚未编译?

And, how can I fetch data before compiling page view controller code? 而且,如何在编译页面视图控制器代码之前获取数据?

I found the answer from comments from this post . 我从这篇文章的评论中找到了答案。
This is the comment. 这是评论。

Move the line print(scenarioArray) and everything you want to do afterwards from viewDidLoad into the completion block after self.scenarioArray = .... 在self.scenarioArray = ...之后,将行print(scenarioArray)以及以后要执行的所有操作从viewDidLoad移至完成块。

The point is 'put other codes in viewDidLoad into completion block(in this code, do block) by making DispatchQueue.main.async { code } in do block. 点是“把其它代码在viewDidLoad到完成块(在该代码中, do块)通过使DispatchQueue.main.async { code }do块。

Here's the answer. 这就是答案。

override func viewDidLoad() {

    super.viewDidLoad()
    var request = URLRequest(url: NSURL(string: "http://xxxxx.xxx/" )! as URL)
    request.httpMethod = "POST"
    var postString = "xxxxxx"
    request.httpBody = postString.data(using: String.Encoding.utf8)

    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            if error != nil {
            return
            }
            guard let data = data else { return }

            do {
                let fetchedData = try JSONDecoder().decode([MyData].self, from: data)
                self.pageTitle.append(fetchedData[x].xx)

                DispatchQueue.main.async {
                    self.pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "pageviewcontroller") as! UIPageViewController
                    self.pageViewController.delegate = self
                    self.pageViewController.dataSource = self
                    self.pageViewController.view.frame = CGRect(x: 0, y: 65, width: view.frame.width, height: view.frame.height)
                    let startVC = self.viewControllerAtIndex(index: 0) as! ContentViewController
                    let viewControllers = NSArray(object: startVC)
                    self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: true, completion: nil)
                    self.addChildViewController(self.pageViewController)
                    self.view.addSubview(self.pageViewController.view)
                    self.pageViewController.didMove(toParentViewController: self)
                 }
            } catch let jsonErr {
                    print("Error serializing json:", jsonErr)
            }
        }
    task.resume()
}


But, be aware of view in CGRect width and height code. 但是,请注意CGRect宽度和高度代码中的view

self.pageViewController.view.frame = CGRect(x: 0, y: 65, width: view.frame.width, height: view.frame.height)

When you put this code in 'do' block, view will bring ambiguous error of. 当您将此代码放在“ do”块中时, view将带来模棱两可的错误。

Then modify that code to this. 然后修改该代码。

self.pageViewController.view.frame = CGRect(x: 0, y: 65, width: self.pageViewController.view.frame.width, height: self.pageViewController.view.frame.height)

Hope this help! 希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM