【问题标题】:ios swift parse: methods with async resultsios swift parse:具有异步结果的方法
【发布时间】:2015-02-27 09:37:38
【问题描述】:

当我转到 viewController 时,我在 viewDidAppear 方法中调用了一个函数:

override func viewDidAppear(animated: Bool) {
    getLessons()
}

此方法从 parse.com 加载我想在 pickerView 中使用的数据列表。 函数本身:

func getLessons(){
        var query = PFQuery(className:"Lesson")
        query.orderByAscending("name")
        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]!, error: NSError!) -> Void in
            if error == nil {

                for object in objects {

                    var name = object["name"] as String

                    self.languagePickerKeys.append(object.objectId)
                    self.languagePickerValues.append(name)

                    self.selectedLanguage.text = self.languagePickerValues.first // set the first lessons name into the text field
                    self.selectedLessonObjectId = self.languagePickerKeys.first // set the first objectId for the lesson

                    self.languagePicker?.reloadAllComponents()

                }
            } else {
                // Log details of the failure
                println("\(error.userInfo)")
            }
        }
        println("getLessons done")
    }

问题是,文本字段是空的,因为 getLesson() 获取数据异步并且数据对文本字段不可用。

我也尝试将 getLesson 放入 viewDidAppear 方法中,但这对我没有帮助,文本字段还是空的。

当视图显示给用户时,我该怎么做才能准备好来自getLessons() 方法的数据并将其第一个值加载到我的文本字段中?

【问题讨论】:

  • 触摸 UI 必须在主线程中完成(如 reloadComponents)
  • 对不起,我不明白你的问题?
  • dispatch_async(dispatch_get_main_queue(), { () -> Void in self.languagePicker?.reloadAllComponents() })
  • Larme,这给了我一个错误:无法将表达式类型 (dispatch_queue_tl, () -> Void) 转换为类型 'Void'
  • 您是否已注销您的对象并检查您是否确实在接收数据? - 你的语言选择器数组是在哪里定义的?

标签: ios swift asynchronous


【解决方案1】:

您当然必须先从 asyncTask 中获取数据,然后再将其设置为 pickerView。

这是实例化后的 ViewController 生命周期:

  • 如果被拒绝,请做好准备。
  • 插座设置
  • 出现和消失。

所以,你有两个选择:

  1. 在之前的 ViewController 中加载数据,然后执行 segue。您需要按照以下步骤操作。

    一个。创建从以前的 ViewController 到您的 ViewController 的 segue。

    b.当你想去下一个获取数据的 ViewController 时调用该函数,最后(在获取数据后)调用 performSegueWithIdentifier 这将导致你的 ViewController。

    c。设置prepareForSegue中的数据

    let navigationController = segue.destinationViewController as UINavigationController
    
    navigationController.data = yourData //you got from async call
    

现在,当您到达您的 ViewController 时,您可以确定您的数据存在,您可以将其设置为您的 pickerView。

  1. 如果你想在同一个 ViewController 中进行:这里是 ViewController 的生命周期:所以你需要在 viewDidLoad 中调用你的函数,并且总是在异步网络调用完成后设置你的 pickerView。

【讨论】:

  • 让我快速更新我当前的代码。但是我仍然有一个问题,即该字段为空并在呈现视图后获取其数据。在文本字段中显示第一个选定的课程之前需要一秒钟。
  • 如果你在后台获取数据,你必须等待获取数据。您可以在 pickerView 上提供加载符号以指示正在进行的提取。
  • 感谢您的回答!无论如何,有没有办法将这些数据获取函数“外包”到一个单独的文件中,以便能够从根控制器调用这些函数并将它们(在我的情况下使用解析本地数据存储引脚)存储在本地?但是床边,我现在更清楚了,谢谢!!
【解决方案2】:

确保从主线程启动对 UI 的所有更改,例如像这样:

dispatch_async(dispatch_get_main_queue(), {
    selectedLanguage.text = languagePickerValues.first
    self.languagePicker?.reloadAllComponents()    
})

【讨论】:

  • 当我添加这个时,我看不到任何变化。文本字段为空,并在我看到视图后不久被填充。在显示视图和将数据加载到文本字段之间仍然存在延迟。
  • 如果这可行但有延迟,Surley 延迟是由于您的解析速度吗?也许您应该在呈现视图之前加载数据。
  • @Wezly 是对的。此外,您正在viewDidAppear: 中开始加载,这已经很晚了(而且不寻常)。你能测量在调用findObjectsInBackgroundWithBlock 和调用它的完成块之间经过了多少时间吗?
  • Wezly,这正是我想要做的!但我不知道怎么做?请解释!
  • 我现在明白的是,如果我在viewDidLoad 中调用getLessons() 方法而不是viewDidAppear,文本会显示得更快,但仍然会有短暂的延迟。我真的很想知道是否有办法在视图呈现之前加载数据......
【解决方案3】:

问题是 findObjectsInBackgroundWithBlock 是一个异步方法,所以即使你在 ViewDidLoad 中触发它,你也永远不会知道你什么时候会收到响应数据,你也不能确定数据是否准备好了视图出现。

我认为您只有两种可能性: 第一个是在前一个视图控制器中加载数据,然后将准备好的数据传递给您的视图控制器。

第二种是使用同步方法(可能是 findobject 方法?)并将调用放在视图出现之前触发的方法中(如 viewWillAppear: 方法)。但是在数据检索时,您的视图会停留片刻(我认为)......但是,第二种解决方案可能会解决您的问题,但是使用同步方法从较慢的数据源中检索数据通常是不好的设计解决方案。

D.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 2014-01-19
    • 2019-03-19
    • 1970-01-01
    • 2018-09-01
    • 2016-06-21
    相关资源
    最近更新 更多