Help me to understand this code snippet - iphone

I would like to know and understand this code snippet
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:#selector(navigatePage)
object:nil];
[queue addOperation:operation];
[operation release];
[queue release];
-(void)navigatePage
//==================
{
[self performSelectorOnMainThread:#selector(loadPageDetails) withObject:nil waitUntilDone:NO];
[myTableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
Thanks for your time.

In a nutshell, the code looks to be designed to do some processing in a background thread -- it is probably fetching some data over the network (loadPageDetails), and then it is updating the UI with the results (reloadData). However, loadPageDetails is being called on the main thread, which I don't understand -- surely that should be done a background thread, if it is time consuming?
Can you give a fuller context for your code? I don't really see the point of using NSInvocationOperation in the above example, because all the operation does is shove more bits of work back on the main thread.
The usual reason for using background processing would be to not block the main thread when doing something that takes time to complete -- I assume the bit of code that sets up the operation queue is called on the main thread?

Related

How perform Some task In Background in iOS

I want perform some database related task in background for that I have added code
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^(void) {
[lclDB deleteRecoredwithBlock:^(BOOL success) {
if (success) {
NSLog(#"Deletion Succesful...");
}
}];
});
deleteRecord function internally calls number of methods sequentially to perform delete operation in local database.now I have wait until all delete operation is performed.but I want to do this whole delete operation in background.if any one known please help me to figure out these problem.
Any NSObject can perform action in background using the following :
[myObject performSelectorInBackground:#selector(anAction) withObject:nil];
More information on apple documentation.
Try performSelectorInBackground:withObject: method.
[self performSelectorInBackground:#selector(backgroundMethod) withObject:nil];
You can also use NSInvocationOperation.
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(deleteDataWithOperation) object:nil];
[queue addOperation:operation];
And this is your deleteDataWithOperation method -
-(void)deleteDataWithOperation
{
//Do your work here
}

How to stop a task initiated using NSOperationQueue?

I have created a process using NSOperationQueue in the below way:
queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(loadDataWithOperation)object:nil];
[queue addOperation:operation];
[operation release];
In the loadDataWithOperation method I wrote code for printing infinite numbers.
Now I have called cancelAppOperations to stop its execution and also I have tried to set suspended value to YES like this
[queue setSuspended:YES]
even though the process is still running, I am calling the stoping method by using "stop"button. It is calling in the same class.
How can I stop it?
You can send a cancellation message to all operations in the queue before they begin executing, but if your operation is already executing you need to process the cancel message
Here for suspend of queue
[queue setSuspended:YES] is working fine,there I check the condition for stop the For loop i.e
if(![queue isSuspended])
{
NSLog(#"elements are :%d",i);
}
else
{
break;
}
I placed these lines of code in "loadDataWithOperation" method

How to Stop a currently executing thread

Scenario is like this--
In my app there is an Scroll View with many instances of
MyCustomImageDownloaderController(containing imageViews where images are to be assigned after downloading) .
As per our requirement, an image has to be downloaded as we move on to a page.
Scroll View + (MyCustomImageDownloaderController1, MyCustomImageDownloaderController2, MyCustomImageDownloaderController3.... etc)
Let's say i am scrolling on it,
i reached to page 1 --> image for it should start downloading
i reached to page 2 --> image for it should start downloading...so on
and if i am on page 3 and images for previous pages if not been dowloaded, they should stop downloading.
So i tried it with using threads..
on API..
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender{
Step 1) calculated currentPageNumber
Step 2) started thread for downloading image with url for this currentPage
//startBackGroundThreadForPlaceImage:(NSURL *) url
Step 3)stopped thread for previous page , if that is still running
}
Now My MyCustomImageDownloaderController is as
-(void) startBackGroundThreadForPlaceImage:(NSURL *) url{
if(isImageDownloaded == NO){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:imageUrl];
myThread = [[NSThread alloc] initWithTarget:self selector:#selector(loadImageInBackground:) object:imageUrl];
//[NSThread detachNewThreadSelector:#selector(loadImageInBackground:) toTarget:self withObject:imageUrl];
[myThread start];
NSLog(#"The current thread is %# ", [[NSThread currentThread] name]);
[pool release];
}
}
NOW Here selector does the work of loading image and assigning to image view
Now Stopping the thread
-(void) stopBackgroundThread{
[myThread cancel];
//[[NSThread currentThread] cancel];
//if([[NSThread currentThread] isCancelled]) {
//[NSThread exit];
//}
[NSThread exit];
}
-(BOOL) isThreadRunning{
return [myThread isExecuting];
}
So i tried a lot of things, but could not Stop the thread in between..
Basically once instantiated thread using any of three methods
1) perform Selector in BackGround
2) NSThread detach new thread
3) NSThread alloc..init with..
In first 2 methods how to get the instance of the newly created thread, so that i could stoop it,
as NSThread currentThread doest not give that
in Method 3,
myThread = [[NSThread alloc] initWithTarget:self selector:#selector(loadImageInBackground:) object:imageUrl];
when i tried
[myThread cancel];
It did not cancel that thread,,
When i tried
[NSThread exit];
it hangs on current screen,,,,i guess it has stopped the main thread
Please help me
Thanks in Advance*strong text*
It's generally better to ask the thread to stop, rather than forcing it, which should be considered a last resort. You should, therefore, frequently check a 'stop flag' and when this gets set, terminate the current thread (by simply exiting the method, in this case). You just need to provide a property on the class the thread is operating on so callers can ask the thread to stop.
It's no different in C++ or Java.

iphone ios running in separate thread

What is the best way to run code on a separate thread? Is it:
[NSThread detachNewThreadSelector: #selector(doStuff) toTarget:self withObject:NULL];
Or:
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(doStuff:)
object:nil;
[queue addOperation:operation];
[operation release];
[queue release];
I've been doing the second way but the Wesley Cookbook I've been reading uses the first.
In my opinion, the best way is with libdispatch, aka Grand Central Dispatch (GCD). It limits you to iOS 4 and greater, but it's just so simple and easy to use. The code to do some processing on a background thread and then do something with the results in the main run loop is incredibly easy and compact:
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Add code here to do background processing
//
//
dispatch_async( dispatch_get_main_queue(), ^{
// Add code here to update the UI/send notifications based on the
// results of the background processing
});
});
If you haven't done so already, check out the videos from WWDC 2010 on libdispatch/GCD/blocks.
The best way for the multithreading in iOS is using GCD (Grand Central Dispatch).
//creates a queue.
dispatch_queue_t myQueue = dispatch_queue_create("unique_queue_name", NULL);
dispatch_async(myQueue, ^{
//stuffs to do in background thread
dispatch_async(dispatch_get_main_queue(), ^{
//stuffs to do in foreground thread, mostly UI updates
});
});
I would try all the techniques people have posted and see which is the fastest, but I think this is the best way to do it.
[self performSelectorInBackground:#selector(BackgroundMethod) withObject:nil];
I have added a category on NSThread that will let you execute threads in blocks with ease. You can copy the code from here.
https://medium.com/#umairhassanbaig/ios-how-to-perform-a-background-thread-and-main-thread-with-ease-11f5138ba380

view hierarchy refresh timing

I'm trying to add a progress meter, or other "I'm busy right now" notification to my view hierarchy right before doing some intense computation that will block the UI. My code looks some thing like:
//create view
[currentTopView addSubView:imBusyView];
//some initialization for the intense computation
[computation startComputing];
Unfortunately, my progress meter doesn't display until after the computation completes. It appears like the views aren't re-drawn until the run loop completes. I'm pretty sure that setNeedsDisplay and setNeedsLayout will also wait until the run loop completes.
How do I get the view to display immediately?
Redrawing only occurs when your code returns control to the run loop. So the easiest way would be for you to schedule the startComputing call with a zero delay. That way, it will be executed during the next run loop iteration (right after redrawing):
[computation performSelector:#selector(startComputing) withObject:nil afterDelay:0.0];
Be aware, though, that unless you do your computation in another thread you will not be able to update the UI during the computation.
If you are doing heavy calculations maybe spawning a new thread is a good idea.
Here I have an activityIndicator displayed and starts a large XMLParse operation in a background thread:
- (void) setSearchParser {
activityIndicator = [[ActivityIndicatorView alloc] initWithActivity];
[self.view addSubview:activityIndicator];
[NSThread detachNewThreadSelector:#selector(getSearchResults:) toTarget:self withObject:[searchParser retain]];
}
then the getSearchResults method:
- (void) getSearchResults: (SearchResultParser *) parser {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[parser startParser];
[self performSelectorOnMainThread:#selector(searchResultsReady:) withObject:[parser data] waitUntilDone:NO];
[pool release];
}
So firstly make a new thread:
[NSThread detachNewThreadSelector:#selector(getSearchResults:) toTarget:self withObject:[searchParser retain]];
this means that all code inside the getSearchResults will be executed on a different thread. getSearchResults also get's passed a parameter of "searchParser" thats a large object that just needs startParse called on it to begin.
This is done in getSearchResults. When the [parser startParser] is done, the results is passed back to the main thread method called "searchResultsReady" and the threads autorelease pool is released.
All the time it took from my parser began to it had finished, a gray view covered the screen an an activityIndicator ran.
You can have the small activityIndicator class I wrote:
-(id) initWithActivity {
[self initWithFrame:[self bounds]];
[self setBackgroundColor:[UIColor blackColor]];
[self setAlpha:0.8];
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityView.center = CGPointMake(160, 240);
[self addSubview:activityView ];
[activityView startAnimating];
return self;
}
- (void) dealloc {
[activityView release];
[super dealloc];
}
Hope it helps you out, even though threads seems a bit confusing, they can help to make the UI not freeze up, which is especially important on the iPhone.