iOS: Wait for an event of button during the loop - iphone

I'm working on a small project in which I need to execute a LOOP to ask questions, and during the LOOP I need to wait for the answer from user before I can perform the next operation.
Any of you could help?

The iPhone's object-oriented framework, Cocoa Touch, already includes the loop you need. There's a class called NSRunLoop that does exactly what you require: it waits for events from the user interface (among other things) and then calls your code to handle the events.
So don't worry about building this loop yourself. Apple has a tutorial that shows how you can build an app that waits for user input and does work based on that input.

You can set all your butons into disabled state:
[myButton setUserInteractionEnabled:false];
After loop is finished, just set it back to true state. This seems to be the easiest possibility.

Related

Can we stop the for loop when app goes background

The for loop is running fetching the data(images and text) from array but when i press home screen button the loop still continues in background and lasts more than 5 seconds which is default time, it should not be more that that as i studied while googling. And when i press home button even then the app delegates respective method like appEnterBackground also called after completion of this loop containing method. So, is it possible to break the loop when the home button is pressed.
Please guide.
If you wanted to detect the entering into background, in addition to responding to the app delegate applicationDidEnterBackground method, you could alternatively register yourself as an observer of the UIApplicationDidEnterBackgroundNotification notification (e.g., using the addObserverForName method of [NSNotificationCenter defaultCenter]).
Note, if you want to cancel your requests, you will want to ensure that (a) the requests are run asynchronously; and (b) they're cancelable. If you're targeting iOS 7 and later, you can accomplish this with NSURLSession (e.g., dataTaskWithRequest or dataTaskWithURL which return a NSURLSessionDataTask object, on which you can call the cancel method if and when desired). Then you can write a handler for the notification that cancels any pending requests.
If you really want to cancel the requests, you can do something like the above, but you alternatively could simply request additional time to complete the requests if the app happens to go into background while the requests are running. This way you get a few minutes to finish requests rather than just a few seconds. See Executing Finite-Length Tasks in App Programming Guide for iOS: Background States.
Or, perhaps even better, you could add your tasks to a background NSURLSession. See the Downloading Content in the Background section of the aforementioned App Programming Guide for iOS: Background States. This way the tasks will continue even after your app is suspended (or, if you app is terminated due to memory pressure). For more information, see WWDC 2013 video, What's New in Foundation Networking.

run a process in the background while user can still use the UI

I am attempting to run a database fetch process in the background without locking the user interface.
Currently I have a button that does this, but I would like it to be automatic so that it can get more results as user is browsing current results.
Here is the code that the button does, I would like to make this automatic and not lock the UI. Also if there is a way to pause the process, but continue where it left off if user goes to another screen that would also be very useful.
Thanks in advance!
-(IBAction)continueUpdatingResultsButtonPressed:(UIButton*)sender{
[findMoreButton removeFromSuperview];
[self continueFindingMoreRecipes]; //(do this in background without locking screen)
[self loadRefreshButton];//At completion load this button (a blinking button) to refresh the cells with new results
}
A typical pattern you can use is something like this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// perform data processing here (done in the background)
dispatch_async(dispatch_get_main_queue(), ^{
// update user interface here (done on the main thread)
});
});
You could do batch requests where you cache the next X amount of answers every time your UI got with in Y of the current end. Depending on what you are using a lot of databases have protocols that can help you batch cache easily. Good luck!
Use grand central dispatch. Create a new queue, dispatch it with a block and when you need to update, call dispatch get main queue. There is no way to pause this once the queue has been dispatched though. Maybe load recipes into intermediary then update as needed.
Look for some gcd tutorials there are a few decent ones there.
Would give you more code but I'm typing on iPhone.
It strikes me (especially since you are, by your own admission, "very new to programming") that it might not be prudent to pursue GCD to prefetch data in a background queue, make sure you coordinate the background queue's database operations with the foreground's database operations (possibly via something like FMDB's FMDatabaseQueue or something equivalent), gracefully handle pausing this operation as you go to other screens (as you indicated in your question) and making sure you don't cause retain cycles in the process.
To make matters worse, I gather that this is all in pursuit of a possibly questionable goal, if I understand you correctly, to retrieve 10,000 recipes in the background. Don't get me wrong. You certainly can design all of the background operations like we've outlined, but I think you should stop and ask yourself whether that's the right design for your business problem.
I might suggest an infinitely easier solution. Just load your tableview with the first x recipes, and as the user scrolls down, when you start to approach the end of the tableview, detect that fact and retrieve the next x records and add them to the tableview. But any user interface that is expecting the user to flip through 10,000 entries doesn't pass the smell test. When I think of a database with 10,000 entries, I think of something more like a imdb/wikipedia/google/facebook-like user interface rather than a contacts-style user interface.
Regardless, you almost certainly don't want your app just endlessly retrieving recipes in the background. You can solve your UI performance issue, but maybe replace it with memory management issues. And you're going to design a complicated system architecture when it's not entirely clear whether your recipe app requires that.

How to build an alarm clock/reminder function in LWUIT?

I'd like to implement an alarm clock/reminder function in a Lwuit application, where the user may set an alarm time, and at that time a reminder dialog pops up with an alarm sound. However, I'm unsure about the approach. So help on any of the below questions would be greatly appreciated:
How to keep a timer running constantly, no matter what Form is displayed, e.g. without interfering with lwuit and EDT?
What's the right way to implement the trigger mechanism that will make the reminder Dialog box pop up? This may happen at any time, no matter what Form is currently displayed and shouldn't interfere with the ongoing user operation, so that when the reminder dialog is closed the user can continue whereever he was when the reminder popped up.
And finally, when the application is closed, or not running in the foreground, how can I keep a timer running? With the new and exiting CodenameOne coming up, I'd obviously like the solution to work on both J2ME, iOS and Android.
Sorry, if the answers are obvious, but I haven't been able to find a solid working solution.
1) You can use java.util.Timer for a generic timer, its callbacks will occur off the EDT so in order to use LWUIT you would just need to callback into the EDT using Display.getInstance().callSerially() and have your code within the Runnable callback.
2) In order to not block input and display in an unobtrusive way you can use the glasspane to just show a translucent element on top of the screen. It will not block input in any way. There is a sample of that in the LWUIT Chat demo application.
3) You can't. Background process execution isn't really supported on any device, all devices have a special "use case based" solution for background execution which requires you to write your applications in a very specific way. Codename One will add support for push notification which will allow you to push an alarm from your server. Seams counter intuitive at first but if you consider the amount of battery life that will be taken up by background processes it becomes pretty obvious why this was done.

How to avoid UI freezes?

Im trying to find the best way to avoid having tiny UI lockups after certain events in my app. For example here are two cases where i have come across mini-lockups:
I have a button that when pressed loads a local mp3 file (around 20-30mb) using AVAudioPlayer, calls the prepareToPlay method and then plays the audio file. The issue is that the button has the showsTouchWhenHighlighted flag set to yes and after pressing it it stays highlighted until the audio file begins playing which could take 1-3 secs.
Another similar example is using a navbar button to sort and reload the table data. There is a very short but noticeable lockup where the button remains highlighted until the table has reloaded.
Can anyone suggest a good approach to minimizing/eliminating these mini lockups? I didnt really come across any code to achieve this in any of the books/tutorials i read that dealt with tableviews and avaudioplayer. Should i be launching these actions on different threads?
thx
For number 1, your best bet is to load the item on a background thread and inform the user that you're doing so (either via a loading HUD or some other indicator). The simplest way of doing this will be to use - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;. If you're running iOS 4.0 + you may want to look into executing block callbacks and see if they will work for you.
For number 2, perform the sorting on the background thread or change your sorting method (consider using a sorted data structure rather than resorting after inserts?). reloadData should occur only on the main thread.
I'm an iPhone noob myself, but it sounds like your code is stuck doing synchronous actions, which will guarantee that your UI gets locked up until the action is done executing.
Although I don't have an explicit answer, look for asynchronous options to perform these actions as they will not lockup your UI. These are usually achieved through using threads or deferred objects. From my experience so far w/ Objective-C, most actions your program neds to take can be achieved through async actions.

When is a Cocoa callback given controll?

I've been searching around the web for an answer to this one, but was unable to find an answer, on the other side I think it's something quite common thus there is a possibility I'm missing some keywords here. Anyhow, the problem is as follows:
When is control given to a callback function in ObjC (iPhone)?
Does it happen after control is given to a high up in the hierarchy class responsible for the runloop? Can it occur in the middle of another function call being executed?
As an example, let's take the NSURLConnection, we don't know or can't predict when it's going to call didReceiveResponse or the other callback methods, can it be the case that didReceiveResponse get's called when I'm in the middle of another function? (highly doubt that but was unable to find information on callbacks wating for the end of the run loop)
Cheers,
Kaspa
can it be the case that
didReceiveResponse get's called when
I'm in the middle of another function?
No, within a single thread, code is not executed in parallel. The runloop schedules the execution of all messages and dispatches them in sequences. Not even NSTimers are guaranteed to fire to the precision they are theoretically capable of because they have to wait for the runloop like everything else.
The callbacks will not be called from in a middle of your function, indeed. You have to give back control to the main runloop for it to process events, and call your callback.
If you want to know who exactly calls your callback, put a breakpoint in it, and check the stack trace.
The only time the didReceiveReponse will be called while something else is executing, is if you have launched the connection on it's own thread (typically in an NSOperation).
This is why when you do have connections in a background thread, you usually use something like performSelectorInMainThread to change the value for other parts of the application - though you can adjust properties directly if they are not marked nonatomic and are not mutable collections.
By default, basically all cocoa touch classes work entirely in a single thread, including many asynchronous operations like background network calls. The main exceptions are NSOperation and friends, and things related to NSThread.
The OS can do this by inserting its callbacks in the run loop schedule. There are also a few cases when one of your calls will also result in a callback on the same stack - for example, if you call resignFirstResponder on an object that notifies its delegate when this happens, such as UITextField.
A couple relevant blog posts:
quick intro to NSRunLoop
Friendly overview of Objective-C callbacks