NSProgress lets you easily and accurately report the progress of work in your app. Understand the concepts behind progress reporting and how to design code that accurately and efficiently reports its progress. Gain specific insights on how to receive progress updates from framework APIs, fold that into your own progress reporting, and show that progress in your app. Hear from the experts about best practices and how to master the NSProgress APIs.
I'm an engineer on the Cocoa frameworks.
And today I'm going to be talking to you
about Best Practices for Progress Reporting,
which in Cocoa means NSProgress.
So I'm going to give you an introduction in NSProgress,
then we'll talk about composing NSProgress objects together,
and then how to use NSProgress as an interface
for cancellation, pausing, and resuming.
Then we'll talk a little bit about hooking NSProgress
up to your user interface, and we'll wrap
up with some tips and best practices.
So let's get started.
NSProgress is an object in Foundation
that represents the completion of some work.
That work could be downloading a file, installing an app,
or something your own application is doing.
The NSProgress object exists to let you easily report progress
in your application across various components,
both yours and the system's.
In fact, several Cocoa APIs are reporting their progress via
NSProgress, like NSBundle Resource Request,
UIDocument, and NSData.
So you can use NSProgress to get information
about what those APIs are doing in your application.
And NSProgress is localized.
You can use it to show information to the user
about what's happening.
And we have ways to influence what it says,
which we'll get to soon.
But first, these are the core properties on NSProgress.
We have the totalUnitCount, which is how much work there is
to do, and the completedUnitCount,
which is how much work has been completed.
And that gets updated as the work occurs.
And the fractionCompleted is a double that gets updated from 0
to 1, letting you know how far along the work is toward
So, totalUnitCount and completedUnitCount,
the unit these properties are referring to is up to you.
It is whatever unit it makes sense
to track in terms of progress.
Perhaps bytes, number of files, photos, or even abstract units
like percentage points or fractions of work.
Each individual NSProgress object has its own idea
of what unit it is reporting in.
And if you don't know how much work there is total,
so you don't know your totalUnitCount,
you can make your progress indeterminant.
And you do that by either setting the completedUnitCount
or the totalUnitCount to a negative value.
Next, let's talk about localization.
NSProgress has two properties, localized Description
and localized Additional Description,
that you can display to the user.
You can set them yourself but NSProgress will also come
up with something for you by default.
So, here is an example of the default localized Description
and localized Additional Description.
We have an NSProgress with a totalUnitCount of 5 million
and some, and a completedUnitCount
of 419 thousand and change.
The default localized Description is 7 percent
completed, and the localized Additional Description formats
those numbers nicely.
So this is the default.
And if you want something different,
you could set the localized Description
and localized Additional Description yourself
but then you would need to actually localize it
in the languages your app supports.
And instead of doing that, we have a couple of knobs
that you can use to alter those defaults.
So the first is through the kind property.
Currently the only option is for files, NSProgressKindFile.
Using this means your units are bytes,
so when NSProgress knows your units are bytes,
it can format them as such,
so you see now it can say 419 kilobytes of 5.3 megabytes.
The other knob for changing the default localized Descriptions
is through certain keys in the user info dictionary.
So NSProgress has a user info dictionary, there is a method,
Set User Info Object For Key, that lets you set a key
and value in the userInfo.
And one key that's useful for virtually any kind
of NSProgress is NSProgress Estimated Time Remaining Key.
The value there is an NSNumber
of how many seconds are remaining
until the work is completed.
And you can see if we set that to, say, 97 seconds,
our localized Additional Description now includes
that information formatted as 1 minute, 37 seconds remaining.
And there are additional userInfo keys that are only used
if your kind is set to file.
First let's look at NSProgress File Operation Kind Key.
This tells NSProgress the type of operation
that is being performed on the file.
The values are either downloading, decompressing,
receiving, or copying, so if you set the File Operation Kind
to NSProgress File Operation Kind Downloading,
that updates the localized Description
to say it is downloading files.
Another key available when your Kind is File is the NSProgress
File URL Key.
And that is an NSURL of the file being worked on.
So when you set that,
the localized Description will include the name of the file,
in this example, photos.zip, which is from the given URL.
There are also options
for if you're operating on a set of files.
NSProgress File Total Count Key and Completed Count Key.
So, here's an example
where we're setting the File Completed Count to 7,
and the File Total Count to 9,
and the localized Description might use that information,
so now it says, downloading 9 files.
Note that the kind is still File and the units are still bytes,
it is just the total bytes of the files being worked on.
And finally, we have the NSProgress Throughput Key.
And that's the bytes-per-second
that the file operations are being performed at.
So, say, it is downloading
at a blazing fast 50,000 bytes-per-second,
if we set the throughput on the userInfo,
the NSProgress can include that information
in the localized Description, so it says,
So, all these options can really provide,
help you provide more information to the user
about what's happening., without you having
to localize it yourself.
Now, before we go any further, we need to talk
There are two sides of NSProgress,
there is the creation side of it, and the client side of it.
First the creation side.
So, when you create an NSProgress, you are responsible
for setting its properties
and updating the completedUnitCount
as the work finishes.
So you're creating it, you're setting the totalUnitCount,
the Kind, setting keys in the userInfo,
and updating the completedUnitCount
as the work finishes.
On the other hand, if you receive an NSProgress
from someone else, you're the client.
You can get and observe the various properties,
the totalUnitCount and completedUnitCount,
the fractionCompleted, or those localizedDescriptions,
but do not go setting those properties
because that's just going to cause confusion
with the creator of the NSProgress.
So when you create an NSProgress, you need a way
to give it to clients, and when you're a client you need a way
to get it.
And one way of doing this is
through the NSProgress reporting protocol, which we added
in OS X 10.11 and iOS 9.
It is pretty simple, and it defines one property, progress.
In Cocoa UIDocument
and NSBundleResourceRequest, both implement this.
And it makes it really obvious
that a class supports progress reporting.
Now, let's do a demo and take a look at some code.
So, here we have an app.
It is pretty basic.
It has a photo, and you hit this import button and it downloads
that photo, and when the download finishes,
it shows it to the user.
Now, that's a pretty awful user experience,
the user has basically no idea what's happening.
And we can make it better by reporting progress
to the user for our download.
So, if we go to our project, we have our download class
that is used to download the photo, and it has an initializer
that takes a URL for it to download,
and it has a completion handler that gets called
with the downloaded data or an error if an error occurs.
Next there is a start method which gets --
which kicks the whole download off, and we have a handful
of private methods for various download-related functionality.
And we also have these convenience methods
that will get called as the download progresses.
So we have Will Begin Download, which gets called
when the download begins
and it gets the total length of the download.
Did Download Data, which gets called periodically
as the download completes.
Did Finish Download gets called when the download is completed,
and Did Fail To Download is called
if there was an error during the download.
So what we're going to do is we want to report progress
about this download operation, and we can do
that by adopting the NSProgressReporting protocol.
So let's go ahead and go up to our class declaration,
and we can add NSProgressReporting
to our list of classes.
And in order to conform to NSProgressReporting,
we need a ProgressProperty.
So let's add that, it's in NSProgress.
And now in our initializer we need
to create our NSProgressObject.
And since we don't know how much there is to download yet,
we're going to make our progress indeterminant.
And one way of making your progress indeterminant is
setting the totalUnitCount to a negative value, so we're going
to set our totalUnitCount to negative 1.
And since we know we're downloading a file here,
we can also give the NSProgress a little bit more information
about what's happening.
So we can set the Kind to NSProgress Kind File,
and we can set in the userInfo,
the NSProgress File Operation Kind Key to Downloading.
So now we have created our NSProgress and now we just need
to update it as the download completes.
So, back to our Will Begin Download method,
that gets the total amount to download.
So we want to set our totalUnitCount to that amount.
And at that point the progress will no longer be indeterminant.
And in our Did Download Data callback,
which is called periodically, we can set our completedUnitCount
to the number of bytes downloaded so far.
And finally, in our Did Download Data callback,
we can set our completedUnitCount
to the total number of bytes in the download,
and that way the progress will be finished.
Now if we, now the user interface is already using
NSProgressReporting and looking for the download
to implement that, and will show the progress, so when we build
and run our app, and we press the import button,
we have a progress being reported for the download
to the user, and it is a much less painful experience.
So, back to slides.
VINCE SPADER: All right.
So, that's the basics of NSProgress.
Now let's get into what really makes NSProgress powerful,
which is the ability to compose progress objects
into other progress objects.
Now, just because I press a download button doesn't mean
that there is really only one thing happening.
There might be the download, a verify,
and a decompress operation all running in reporting progress.
But the user only sees one progress bar.
So, let's say that these boxes represent individual
They each report their own progress in their own units
without having to worry about the others.
But we want them to be combined into a single NSProgress
that we hook up to the user interface.
So we're going to create an NSProgress object
and call it the overall progress.
And we can compose these other progresses
into our overall progress,
the overall progress becomes a parent
of these other three progress objects, the download, verify,
and decompress progresses are its children.
And as those children complete,
the overall progress will be updated.
So for composing NSProgress objects, we have this idea
of a pendingUnitCount.
The pendingUnitCount is a portion
of the parent's totalUnitCount that gets assigned
to a child progress object.
The pendingUnitCount is in terms of the parent's units,
the child has its own units,
and we say that the parent's pendingUnitCount is assigned
to the child.
So what happens is, when a child progress finishes,
the parent's completedUnitCount is incremented
by the pendingUnitCount for that child.
So when you have a child,
you don't update the completedUnitCount manually,
that might conflict with an update that happens
when your child finishes.
When your at parent progress, you really want
to assign your entire totalUnitCount to children.
So let's go over a diagram of composition.
Let's say we're importing some photos.
So we have the overall import NSProgress object.
There are two photos total, so the totalUnitCount
for our import progress is 2.
And it is going to assign its entire totalUnitCount
to its children, which are the progresses
for the individual photos below.
So each photo is assigned a pendingUnitCount of 1 photo
from the overall import progress.
Now, the individual photo progresses are similar
but their unit is different,
they have a totalUnitCount of two steps.
And each step is taking up one pendingUnitCount,
one for the download and one for the filter.
And finally we have the download and filter progresses.
They have their own units.
They have no children.
And they update their completedUnitCount manually.
So I brought in the completedUnitCounts here.
That's the zero of.
And the fraction completed is the percentage at the bottom.
Since we haven't done anything yet, it starts at zero.
And let's see what happens as the completedUnitCounts
at the bottom are updated.
So you can see these -- as these children complete,
the fraction completed is updating in the parents.
Progress kind of flows up to the parent.
And note that the completedUnitCount
for the overall progress is still zero.
The completedUnitCount is only incremented once the child is
finished and photo 1 still isn't finished.
And once a child does finish,
the completedUnitCount is incremented
by the pendingUnitCount for the child.
You can see that the import progress now has one photo
complete since photo one is now 100% finished.
The fraction completed, on the other hand, is multiplying
up based on the pendingUnitCount
and the fraction completed of the child.
It doesn't wait until the child is finished to update.
And when everything is at 100%, the import progress is finished,
and that's an example of what happens
when you're composing NSProgress objects.
Now let's zoom in here.
Here we have a progress for an individual photo's import,
so this is just one photo.
There are the two steps, download and filter.
So we have a totalUnitCount of 2.
And we say the download is going to take one of those units
and the filter is going to take one of those units.
So each step takes up half of the photo's overall progress.
But what if these operations aren't equal?
What if we know that the filter is pretty quick relative
to the time to download, so it looks something more like this?
Well, units can be arbitrary.
You can say that there are actually ten steps
and the download is assigned nine of those,
and the filter is assigned one.
And now as the download completes,
the download step takes up 90% of the import progress
and the filter takes the remaining 10%.
So you can modify the units of the progress in order
to weight the work being assigned to children.
Let's see how to actually do this in code.
There are two ways of composing NSProgress objects
and the first way I'm going to talk
about is implicit composition.
So you create a parent progress object.
This will be the photoProgress from before.
So there are two steps.
And we have -- so we have a totalUnitCount of 2.
And what we want to do, is add a download progress as a child.
So we call become Current With Pending Unit Count
on the parent progress, the photoProgress.
And what this does is it sets a thread local current progress
so the photoProgress is the current progress,
and that pendingUnitCount of 1 is set aside
and basically reserved for progress to come along
and get added to the current progress.
And next we call our download function, startDownload,
and that creates a progress with the NSProgress
with totalUnitCount convenience constructor,
and with totalUnit convenience constructor,
we'll add the created progress to the current progress.
So the download is added as a child of our photoProgress.
Next we need to clean this up.
So we call resigned current
and the photoProgress is no longer the current progress.
And that's it.
Now we've used implicit composition
to add a child to a parent.
A few things to remember when using implicit composition,
when supporting implicit composition,
you want to create the NSProgress immediately using the
with totalUnitCount convenience constructor.
That's because the first progress object added
to the current progress takes up that entire pendingUnitCount.
And if you create it first thing, you don't have to worry
about getters or other calls unintentionally taking
up the parent's pendingUnitCount.
Also, be sure to document it.
Implicit composition is implicit after all,
clients won't know you support implicit composition unless you
Also, if no child is added
by the time you call resigned current,
that pendingUnitCount will be immediately added
to the parent's completedUnitCount.
So your completedUnitCount will be updated.
So, the second way to compose NSProgress objects is new
in OS X 10.11 and iOS 9,
and that's called explicit composition.
So, you receive a progress that you want to add
as a child from somewhere.
Perhaps something that conforms
to the NSProgressReporting, we'll say a filter.
And you have your parent progress
that you want to add it to.
Let's say the photoProgress from before.
Then you simply call addChild with pendingUnitCount
on the progress you want to add it to,
and path in your child progress, the filterProgress, here,
and give it the pendingUnitCount you want to add it with,
since it is one step, we want to add it with a pendingCount of 1.
And that's it.
Now your progress is a child of the parent progress.
So here are some guidelines for when to use explicit
or implicit composition.
If you have a method that can't return in NSProgress
like you're crossing an API boundary you can't change,
use implicit composition and document
that it supports implicit composition.
Or, because explicit composition is new in OS X 10.11 and iOS 9,
you'll have to use implicit composition on older releases.
Otherwise, you will generally want
to use explicit composition; it is a lot simpler.
Now let's go through a demo of composition.
So here we have our photo download class
that we added our progress reporting to last time.
And if we run our app, it has been changed a bit.
Now it has a CollectionView
of photos instead of a single photo.
So, and when we press import,
instead of just downloading those images,
it is also running them through a filter.
So we don't have progress information
for that overall thing, so the experience is pretty bad.
And again, we can make it better
by having our operations report progress.
So let's do that.
So we have our download class
that supports NSProgressReporting,
and we have our filter class, which has a class method
that takes an image and returns a filtered image.
And we have this import class, which has both the download
and runs the filter when the download completes.
So it combines the progress for --
we want it to combine the progress for the download
and the filter operation.
So let's look at our photo import.
It has an initializer, which takes a URL
and it creates the download with that URL.
It also has a completion handler that gets called
with the filtered and downloaded image,
or an error if an error occurs.
And it also has a start method for starting the import.
And the start method sets the completion handler
on the download, and then creates a UIImage
from the downloaded data, and then passes that image
into our filter, getting out our filtered image,
and then calls its own completion handler
with the filtered image.
And once the completion handler is set, it starts the download.
So what we want to do is have our photo import report a
combined progress comprising of both the download
and the filter's progress.
And we are going to do that again
by having our photo import class conform to NSProgressReporting.
So let's go up to our class declaration
and add NSProgressReporting.
Now we need to have a progress property, so let's add that.
ANd we need to create our NSProgress object.
And this time for our units we're going
to use something a little abstract.
We have run the app a few times and we've found
that if we have the download take up about 90%
of the import's progress, that feels pretty good.
So we're going to have a totalUnitCount of 10,
and we're going to say the download takes up 9
of that totalUnitCount and the filter is going
to take up the remaining 1.
So now in our start method,
since the download already conforms to NSProgressReporting,
we can just get the progress object from it and add it
to our progress, and we can do
that with the explicit add child method.
So we're calling progress add child download progress,
and our pendingUnitCount is 9,
so it takes up 90% of our progress.
And now we want to also add the filter's progress
to our progress.
But the filter is a class method
that takes an image and returns an image.
There is no obvious way to get a progress out of it.
But, if we go to our photo filter class,
we can see a comment here
that says it supports implicit progress composition.
So we can use implicit progress composition
to add it as a child.
So let's go back to our import start method.
And in the downloads completion handler, which might be called
on a background thread, we're going to become current
with the pendingUnitCount of 1.
And note, like I said, the completion handler
for the download might be called in a background thread,
but that's okay because we're calling the filter immediately
after on the same thread.
So, after we become current, our filter will run
and it will add itself as a child to the current progress,
and once it returns, we need
to no longer be the current progress, so we're going
to call resign current.
And that's it.
Now we have added both the download and the filter progress
to our import progress.
And now if we run our app, and we press import,
you can see the imports are reporting progress
for each photo.
And that's good, the user has more information
on what's going on, but it is not really that great.
We only want one progress to show to the user.
So let's do that.
So we're going to zoom out a little bit and we're going to go
to our root View Controller, photos View Controller,
and this has an overall progress property.
It is a client of this NSProgress, it just gets it,
and it is going to hook it up to the UI and show it.
It is not going to create it itself.
And it also has a reference to an Album,
which is the collection of photos that we're downloading.
And it has IBActions for the toolbar buttons,
in this case the start import button
and that IBAction just calls import photos on our album.
So if we look at our album it has an array of photos,
and it creates the photos from URLs in the main bundle,
and in its import photos method it goes through each photo
and calls start import on them.
Now if we look at our photo, our photo has an image URL
that it gets in its initializer,
and it also has a UIImage property that starts
out as a place holder.
It also has its start import method
that is getting called by the album.
It creates that photo import class
that we added NSProgressReporting to,
and then sets a completion handler
for that photo import class, to set the image
as the image that's been imported.
And it is then, after the completion handler is set,
it starts the import and stashes it away in case it needs it.
So what we want to do is we want
to get the photo imports progress and collect them
into a progress for all of the imports that are happening.
So let's go back up to our root View Controller.
And what we can do is we can say
that our import progress method returns that NSProgress.
so we're going to set our overall progress property
to that returned NSProgress.
And import photos doesn't return in NSProgress yet,
so we need to go do that.
So let's go to our album and its import photos method.
And it is currently returning void.
And we need to make it return in NSProgress.
Then we need to create the progress object
that we're going to return.
And since this progress object is going to have a child
for every photo in our album, we want our totalUnitCount
to be the number of photos in the album.
And also let's go ahead and return it.
And what we're going to do is we're going
to have our photo start import method also return a progress,
so we're just going to assign
that to a local variable import progress.
And then we're going to add that as a child to our --
to the album's progress with the pendingUnitCount of 1,
since this is the import progress for one photo.
And now, in our photos start import method,
it is currently returning void.
We want in to return in NSProgress, so let's do that.
And since our photo import already conforms
we can just return the progress property from it.
And that's it.
We have quite a composition happening now.
We have that overall progress being assigned
to a progress made up --
that has children for each import that's happening,
and each of those imports has both a download
and a filter child.
So let's run the app.
And now we have an overall progress at the bottom
that gets updated as all those children complete.
Removing all of the smaller progress bars is left
as an exercise.
VINCE SPADER: Okay.
Back to slides.
So now I would like to talk a little bit about cancellation,
pausing, and resuming.
NSProgress objects can be a conduit for cancellation.
The creator of the NSProgress sets cancelable
and the cancellationHandler.
If your operation is doing some work synchronously and
and the cancellationHandler doesn't really work,
you can pull the canceled flag
on the NSProgress object as well.
A client can call cancel and the NSProgress will set cancel
to true and invoke the cancellationHandler.
So cancellation flows down to children.
So if you have child progresses with cancellation handlers,
those will be invoked too.
And it is permanent.
Once a progress is canceled, there is no uncanceling.
Pausing is pretty similar to cancellation.
The creator of the NSProgress sets pausable along
with a pausing handler and resuming handler.
That resuming handler is actually new
in OS X 10.11 and iOS 9.
And you can also pull that paused flag to determine
if the progress is currently paused.
Clients can call pause and will set pause
and call the pausing handler, or they can call resume
and will unset pause and invoke the resuming handler.
Pausing and resuming also flows
down to child progresses just like cancellation.
And let's go ahead and do a demo of that.
So if your objects, if your operations already support
cancellation, pausing, and resuming,
it is actually really easy to expose that through NSProgress.
So we're back in our photos View Controller.
And this is our root View Controller.
And this time the app has a few more buttons.
So if you press import, there is also a cancel and pause button,
but they don't really do anything right now.
And we need to hook them up.
So let's do that.
So we have our IBActions defined for those buttons,
we have cancel import, pause import, and resume import.
And what we're going to do is we're going to call cancel,
pause, and resume on the overall progress inside
of those actions.
And now once -- and now that will call any cancellation,
pausing, or resuming handlers on any child progresses.
And we don't have any yet,
but our download does support cancellation,
pausing, and resuming.
So let's go to our photo download.
And if we go down to our Will Begin Download callback,
we can add cancellation, pausing,
resuming support to this NSProgress.
So first we set cancelable to true,
and we set our cancellationHandler,
and here our cancellationHandler is calling Failed Download
With Error with an NSUser Canceled Error.
And we also are pausable and resumable, so we're going
to set pausable to true, and in our pausing handler we're going
to call this Suspend Download method.
And in our resuming handler, we're calling Resume Download.
Now, note that these are all private, the Failed Download
With Error, Suspend Download, and Resume Download methods,
so we're only exposing this functionality for canceling,
pausing, or resuming through NSProgress,
so it can be a pretty powerful point of interaction.
Now when we run the app, and we compress, start our import
and pause, and the progress, the download pauses itself,
and we press resume, and it resumes,
and we can hit cancel, and it gets canceled.
And what's happening is that overall progress is sending --
invoking any cancellationHandlers
for any children it might have.
And that's it.
Back to slides.
VINCE SPADER: All right.
So let's talk a little bit about the user interface.
We have gone through all of this trouble
of creating these NSProgress objects,
but their ultimate purpose is to give the user an idea
of what's happening, and that means the user interface.
So all of the properties
on NSProgress are key value observable,
clients can add the KVO observers to update their UI.
For example, a client can update their UI progress views progress
with the NSProgress as fractionCompleted property,
or update a label with a localizedDescription.
Also be aware, that these KVO callbacks might not necessarily
be called on the main thread.
So if you're updating UIControls, you want to move
that work to the main queue.
So here is an example of what
that adding an observer might look like.
You call addObserver for key path on the NSProgress
for the fractionCompleted property.
Then in our override of observe Value
For Key Path we enqueue some work on the main queue,
and on the main queue we get the fractionCompleted
from the NSProgress, and update our UIProgressView.
And that's basically it.
You can use a similar pattern for updating labels
or buttons in your UI.
All right, finally, let's go
over some best practice for NSProgress.
Since this talk is called best practices, I better squeeze some
in at the last minute.
So, first is completion.
Don't use fractionCompleted to determine completion.
It's a floating point value determined --
derived from a calculation.
So comparing it to 1.0 won't always be right.
Use completedUnitCount and totalUnitCount instead,
unless your progress is indeterminant
or the totalUnitCount is 0.
It is important, by the way, that progress is finished.
The parents completedUnitCount only gets updated
when the child finishes.
And also NSProgress can optimize a way of completed children
so memory can be saved as work finishes.
Next, NSProgress objects cannot be reused.
Once they're done, they're done.
Once they're canceled, they're canceled.
If you need to reuse an NSProgress,
instead make a new instance and provide a mechanism
so the client of your progress knows
that the object has been replaced, like a notification.
Don't update the completedUnitCount
in a tight loop.
So, for example, don't update it every byte of a download.
If you have a parent, we might be calling
up to update the fractionCompleted,
which might take longer than you're expecting
since your composition can be arbitrarily large and very deep.
But when you do so, don't forget to finish the progress.
So be sure to update the completedUnitCount
to the totalUnitCount.
Otherwise you're going to be left
with nearly finished progresses.
And that's no fun.
So that's it.
We talked a lot about how to use NSProgress effectively.
If there is anything to remember, it is these points.
Each progress has its own unit.
You can compose them either implicitly or explicitly.
And when you do, the pendingUnitCount is
in the parent's units.
Also you either create the NSProgress or you're a client.
For localization, you can use the kind and userInfo properties
to help us give you a better localizedDescription.
NSProgress can be a really nice interface for cancellation,
pausing, and resuming.
And all its properties are KVO observable, so you can use it,
use that to update your UI.
For more information, see the documentation;
also check out the header for NSProgress,
it is extremely well commented.
We have some new sample code, photoProgress,
which is based off the demos I showed today.
If you need any help, try the developer forums
or contact developer technical support,
and for general inquiries, email Paul Marcos.
And that's all.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.