I have 6 functions. I would like to execute 3 of these functions in the background (asynchronous?), in Xcode for Swift 2. Can you help me, how can I execute this 3 functions without a "freeze" in the UI? Thank you so much!
Martin R's comment is spot on, you should read Apple's concurrency programming guide. But here's one method you might use:
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
dispatch_async(queue) {
doSomethingReallySlowAndTedious()
}
Be careful, though. It's especially easy to introduce bugs in your code by just copy-pasting concurrency code. Make sure you know what each function and parameter does.
(Also, consider the worst cases. Can the slow functions get stuck forever? What if the user wants to quit before the slow functions finish?)
Related
In a Udacity's GCD course there was a small quiz:
let q = DispatchQueue.global(qos: .userInteractive)
q.async { () -> Void in
print("tic")
}
print("tac")
Which will be printed first?
The correct answer is: tac, then tic. Seems logical.
But, why is it so only when I create an Xcode project? In a playground it prints tic then tac. What am I missing?
In GCD
DispatchQueue.global(qos: .userInteractive).async{}
is below
DispatchQueue.main.async{}
Even thought it has quality of service (qos) as UI thread it does not means it is a main thread. So may be there is a difference in performance with play ground and ui project
please check apples documentation as well.
Apples documentation on GCD
key to your answer is in the question what really are you asking the "system" to do, an by system that is the whatever the code is running on the playground, your computer/phone or emulator. You are executing an asynchronous "block" of code - print("tic") with some priority ".userInteractive". If the system handles the asynchronous block first or continues with "normal" execution depends on priority and available resources. With asynchronous calls there is no real why to guarantee that it is executed before or after the code continues that is the nature of being asynchronous i.e execute the block as soon as the system allows it, all without blocking your current work. So the difference you are seeing in playground vs a project/emulator is that the project/phone/emulator must keep the UI/primary thread responsive so it continue with print("tac"), while the development playground favors the thread executing print("tic"). Bottom line is it has to deal with priority of execution and the available resources and how its implemented on the system you're running the code.
If I have a function call that returns true or false as the condition of an if statement, do I have to worry about Swift forking my code for efficiency?
For example,
if (resourceIsAvailable()) { //execute code }
If checking for the resource is computationally expensive, will Xcode wait or attempt to continue on with the code?
Is this worth using a completion handler?
What if the resource check must make a database call?
Good question.
First off... can a function be used? Absolutely.
Second... should it be used?
A lot of that depends on the implementation of the function. If the function is known (to the person who wrote it) to take a long time to complete then I would expect that person to deal with that accordingly.
Thankfully with a lot of iOS things like that are taken out of the hands of the developer (mostly). CoreData and Network requests normally come with a completion handler. So any function that uses them would also need to be async and have a completion handler.
There is no fixed rule for this. My best advice would be...
If you can see the implementation of the function then try to work out what it’s doing.
If you can’t then give it a go. You could even use the time profiler in Xcode profiler to determine how long it is taking to complete.
The worst that could happen is you find it is slow and then change it for something else.
I'm fairly new to using Google Docs, but I have come to really appreciate it. The scripting is pretty easy to accomplish simple tasks, but I have come to realize a potential speed issue that is a little frustrating.
I've got a sheet that I use for my business to calculate the cost of certain materials on a jobsite. It works great, but was a little tedious to clear between jobs so I wrote a simple script to clear the ranges (defined by me and referenced by name) that I needed emptied.
Once again, worked great. The only problem with it is that clearing a few ranges (seven) ends up taking about ten full seconds. I -believe- that this is because the spreadsheet is being saved after each range is cleared, which becomes time intensive.
What I'd like to do is test this theory by disabling autosave in the script, and then re enabling it after the ranges have been cleared. I don't know if this is even possible because I haven't seen a function in the API to do it, but if it is I'd love to know about it.
Edit: this is the function I'm using as it stands. I've tried rewriting it a couple of times to be more concise and less API call intensive, but so far I haven't had any luck in reducing the time it takes to process the calls.
function clearSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
sheet.getRange("client").clear();
sheet.getRange("lm_group_1").clear({contentsOnly:true});
sheet.getRange("lm_group_2").clear({contentsOnly:true});
sheet.getRange("dr_group_1").clear({contentsOnly:true});
sheet.getRange("dr_group_2").clear({contentsOnly:true});
sheet.getRange("fr_group_1").clear({contentsOnly:true});
sheet.getRange("fr_group_2").clear({contentsOnly:true});
sheet.getRange("gr_group_1").clear({contentsOnly:true});
sheet.getRange("client_name").activate();
}
That is not possible, and will probably never be. It's not "the nature" for Google Docs.
But depending on how you wrote your script, it's probable that all changes are already being wrote at once, in the end. There's some API calls that may be forcing a flush of your writings to the spreadsheet (like trying to read after you wrote something), but we'd need to see your code to check that.
Anyway, you can always check the spreadsheet revision history to verify if it's being done at once or in multiple steps.
About the performance, Apps Scripts have a natural delay that is unavoidable, but it's not 10s, so there's probably room to improve on your script, using fewer API calls and preferring batch calls like setValues over setValue and so on. But then again, we'd have to see your code to assert that and give more helpful tips.
I have a method in my iPhone app that is very repetitive (called over and over and over sequentially). The method is quite bulky and takes about one second to complete.
My question is this: If I was to muti-thread it to run, say 5 method calls on different threads simultaneously, would that be any faster than running 5 calls one after another? I know of desktop machines with multi-core processors this would be an advantage, but I am not sure about the iPhone.
Any advice?
Use Grand Central Dispatch (aka GCD and libdispatch) and it'll just Do The Right Thing(tm).
If you call dispatch_async on one of the global queues, GCD will figure depending on system workload whether to spawn new threads to handle the operations you submit, or whether to run them in series on one thread.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do your calculations here
// If you want to run code on the main loop with the result of the calculations,
// do something like this
dispatch_async(dispatch_get_main_queue(), ^{
// Code to run on the main thread here
});
});
You could also use dispatch groups to run some code after all five calls have completed.
Take a look at the Concurrency Programming Guide and the GCD reference manual for details.
Update
Also look at this article from Ars on GCD. They explain some of the details of how GCD decides how to schedule blocks.
If it's something like a network request, it will most probably be faster because you're spending time waiting without really using the processor (although spawning threads is not really the best way to deal with that). But if the method is doing some heavy calculations you won't gain anything. Still, to keep the UI responsive you would run lengthy tasks in the background. It's usually better and simpler to use NSOperation for such things, so have a look at that class.
Try it, there is no better answer. It’s not hard:
- (void) startInParallel {
for (int i=0; i<5; i++)
[self performSelectorInBackground:#selector(doSomeWork)];
}
Plus you might want to add some time measuring. Then, if you find out that running all the operations in parallel really makes sense, you can use NSOperations or GCD to do it. (I just hope that performSelectorInBackground does not have enough time cost to skew the test results.)
Normally I'm well aware that a consideration like this is premature optimization. Right now I have some event handlers being attached inside a foreach loop. I am wondering if this style might be prone to leaks or inefficient memory use due to closures being created. Is there any validity to this thinking?
closures only apply if your event handlers are anonymous methods (including, but not limited to, lambda expressions). If this is the case, you might have a problem. But it should be okay as long as you remove these event handlers at the proper time.
If you are talking about something like this:
foreach (var item in items)
{
item.SomeEvent += delegate {
// do something
};
}
Then the answer is the performance is not noticeable (in my Monotouch experience anyway) as the compiler simply creates a class with a method the same way the Microsoft C# compiler.
The biggest performance bottlenecks I've encountered in Monotouch have been SQLite related, and parsing DateTimes. Everything else, including complex LINQ statements fly on the 3GS - I'm not sure what magic is performed by the AOT compiler but I would only worry if it creeps up into 0.5 or more seconds to perform the task.