我正在尝试在向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动画。 我在整个代码中的多个地方调用此函数(尤其是整个应用程序中的按钮)。
但是,每当调用此函数时,动画都不会显示,直到整个过程完成。 为什么是这样?如何在生成和保存新内容时显示动画,然后在完成后将其关闭?
答案 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
;您的函数可能在队列完成并创建和保存日历之前返回。