加载动画仅显示按钮功能(Swift)

时间:2016-01-23 00:33:00

标签: ios swift animation save loading

我正在尝试在向NSUserDefaults生成并保存新数组时显示加载动画。动画函数在下面显示的函数中调用:

    func getOrCreateCalendar(forYear: Int) -> [DetailedDate] {
       if forYear == date.getDateComponents(todaysDetailDate.date).year && calendar.count > 0 {
           print("forYear == today's year and the current calendar has been RETURNED FROM MEMORY")

           return calendar
       } else {
           let existingCalendar = getExistingCalendar(forYear)

           if existingCalendar != nil {
               return existingCalendar!
           } else {
               SwiftSpinner.show("Generating new calendar for \(forYear)", animated: true)

               let calendar = generateCalendarFor(forYear)

               print("GENERATED NEW calendar for \(forYear)")

               SwiftSpinner.show("Saving calendar", animated: false)

               saveNew(calendar, year: forYear)

               SwiftSpinner.hide()

               return calendar
           }
       }

我正在使用如上所示的开源SwiftSpinner动画。 我在整个代码中的多个地方调用此函数(尤其是整个应用程序中的按钮)。

但是,每当调用此函数时,动画都不会显示,直到整个过程完成。 为什么是这样?如何在生成和保存新内容时显示动画,然后在完成后将其关闭?

1 个答案:

答案 0 :(得分:1)

尝试使用以下代码在后台队列中执行操作:

SwiftSpinner.show("Generating new calendar for \(forYear)", animated: true)
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), {
    let calendar = generateCalendarFor(forYear)

    print("GENERATED NEW calendar for \(forYear)")

    dispatch_async(dispatch_get_main_queue(), {
        SwiftSpinner.show("Saving calendar", animated: false)
    })

    saveNew(calendar, year: forYear)

    dispatch_async(dispatch_get_main_queue(), {
        SwiftSpinner.hide()
        onCompletion(calendar)
    })
})

你在这里做什么:

  • 您创建了一个后台队列
  • 创建日历
  • 从主队列(dispatch_async(dispatch_get_main_queue(), { SwiftSpinner.show("Saving calendar", animated: false) })更新UI(主队列很重要,因为只需从主队列修改UI shpuld)
  • 保存日历(再次在后台队列中)
  • 调用自定义函数(此处我在主队列中将其命名为onCompletion,它对日历执行某些操作(替换return calendar

您应确保在调用dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { ... })之前禁用您的UI按钮等,并在onCompletion中再次启用,否则用户可以在应用运行时按某些按钮(和也许改变队列使用的一些数据 - >不好。)

<强>为什么: UI从主队列更新,但通常不会在您调用代码更新后立即更新;如果阻止主队列,则无法更新UI。因此,我们在后台队列中完成工作,以便您的主队列可以更新UI。

详细信息: 您调用dispatch_async(来自GrandCentralDispatch),它创建一个优先级为QOS_CLASS_USER_INITIATED(〜普通优先级)的新队列。然后它将花括号中的代码传递给此队列;操作系统将在一个单独的线程中执行队列。 由于必须仅从主队列修改UI,因此我们再次使用SwiftSpinner.show("Saving calendar", animated: false)将用于更新UI(dispatch_async)的代码传递到主队列。

使用完成函数是必要的,因为代码/队列在后台执行,独立于getOrCreateCalendar;您的函数可能在队列完成并创建和保存日历之前返回。