IOS/Xcode: Breakpoint in completion block possible? - ios

I am trying to debug something going on in a completion block. I put a breakpoint in the completion block, but the code is not breaking. Is it possible to put a breakpoint in a completion block? I recall it being possible but cannot seem to find any confirmation in the docs or on the Internet.
dispatch_async(dispatch_get_main_queue(), ^{
LogDebug(#"ready to save to database if this was new to server");
Items *object = [self.managedObjectContext objectRegisteredForID:myMoID];
//TRIED PUTTING BREAKPOINT RIGHT HERE BUT NOT STOPPING
if (successInt==1) {
object.needsync=#0;
}
});

You should always put a breakpoint on a line where some code is, not an empty line, it works better.
If your log is not printed out in a console, it means your block is never called.

If your code is not breaking this means that your completion block is not being called. Try to print log in completion block to check that if it is being called or not.

Related

Xcode run to wrong method with same signature

I'm encountering some problem with SVPullToRefresh.
I'm trying to debug by placing breakpoints in the library. It's strange that no breakpoint is reached after I run.
Then I place breakpoint at my calling as this:
[self.tableView addPullToRefreshWithActionHandler:^{ // break point at this line
[weakSelf needReloadData];
}];
Then I run debug step into. Wow, what function does it call? It does not call the function in UIScrollView (SVPullToRefresh) in UIScrollView+SVPullToRefresh.m file.
It call the function in UIScrollView(Adobe3SVPullToRefresh) in UIScrollView+Adobe3SVPullToRefresh.m line 115. See the image
What happen with this? Thank you

ios: waiting for method to finish executing before continuing

I am new to IOS development and am currently facing a problem.
When method A is called, it calls method B and then it wait for delegate connectionDidFinish which connectionDidFinish will execute MethodC.
My question is how do I ensure that methodA to methodC has finished executing before executing NSLog?
I found that a way to solve this problem is to use notification center. Send notification to me after finishing executing methodC. I don't think this is a good solution. Is there another way to do this?
Example:
[a methodA];
NSLog(#"FINISH");
If any of those methods perform actions asynchronously, you can't. You'll have to look into a different way of doing this. I personally try to use completion blocks when ever I can, although it's perfectly fine to do this other ways, like with delegate methods. Here's a basic example using a completion block.
- (void)someMethod
{
[self methodAWithCompletion:^(BOOL success) {
// check if thing worked.
}];
}
- (void)methodAWithCompletion:(void (^) (BOOL success))completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^{
// go do something asynchronous...
dispatch_async(dispatch_get_main_queue(), ^{
completion(ifThingWorked)
});
});
}
In the code you posted, methodA must finish executing before the log statement will execute.
However, if methodA starts an asynchronous process that takes a while to finish and returns before it is finished, then you need to do something different. Usually you don't want to freeze the user interface while you are waiting, so you set up a delegate, pass in a completion block, or wait for an "ok, I'm done" notification.
All those are very valid, good ways to solve the problem of waiting for asynchronous tasks to finish running.
Newer APIs are starting to use completion blocks. Examples are:
presentViewController:animated:completion:, which takes a completion
block that gets called once the new view controller is fully
on-screen and "ready for business.
animateWithDuration:animations:completion:, which takes a completion
block that gets executed once the animation is finished, and
sendAsynchronousRequest:queue:completionHandler:, which starts an
asynchronous URL request (usually an HTTP GET or PUT request) and
provides a completion block that gets called once the request has
been completed (or fails)

Execute after a function call

I have a function call and some coding statements after the function. These statements should be called only after the function is executed completely How can it be achieved? Currently the statements are executed before the function is executed completely.
For example
NSInteger integerRestValue=[self buttonRestNameTag];
buttonRestNames.titleLabel.text=[[arrayGuessList objectAtIndex:integerRestValue]valueForKey:#"Name"];
Here the buttonRestNameTag function is called and before the execution is completed the buttonRestNames title label is set which cause it to crash.
How can this be resolved?
You may have initialized another Thread inside your function buttonRestNameTag.
Check that thing.
Or Try to use this function :
[self performSelectorOnMainThread:#selector(functionName) withObject:nil waitUntilDone:YES];
Hope this helps.
Edit for Kiron :
Make a variable in class and put returned value in that and access that variable.
This is helpful link to do this
iphone - performSelectorOnMainThread with return value
You can use GCD blocks
Try this.

Variable returning null after block execution

I am dispatching a queue to download some flickr photos on a separate thread (in viewWillAppear). When I log the contents of the array inside the block, it shows everything perfectly:
dispatch_queue_t photoDowonload=dispatch_queue_create("photoDownload", NULL);
dispatch_async(photoDowonload, ^{
NSArray *photoList=[FlickrFetcher topPlaces]; //downloads flickr data
self.listOfCities=photoList;
NSLog(#"inside block: %#", self.listOfCities); //shows contents
});
but when I try to log the array that was set inside the block outside the block, it returns null.
dispatch_queue_t photoDowonload=dispatch_queue_create("photoDownload", NULL);
dispatch_async(photoDowonload, ^{
NSArray *photoList=[FlickrFetcher topPlaces];
self.listOfCities=photoList;
});
NSLog(#"after block: %#", self.listOfCities); //returns null
What's the problem here? self.listOfCities is set up as NSArray property so once it's set in the block, it should be accessible outside of it.
The code in the block is run asynchronously. So the code after the block is run before the code in the block has had a chance to run (or certainly complete at least).
I've just started learning Objective-c, and I can be blind for some kind of issues but I'm wondering what is the impact of the _dispatch_asynch_ on executing block of code shown above.
Docs says
The dispatch_async() and dispatch_sync() functions schedule blocks for concurrent execution within the dispatch framework.
Maybe NSLog is called before execution of code block and variable is not initialized yet.
#rmaddy You was faster.
Ok I figured this out. My goal was to update the tableView with the info returned by block.
The block execution was changing the array variable but that change was not getting shown.
The trick was to detect this change in the getter for the array as follows:
-(void) setListOfCities:(NSArray *)listOfCities
{
if (_listOfCities!=listOfCities)
{
_listOfCities=listOfCities;
[self.tableView reloadData]; //<-- reloads table after change
}
}

iOS - Grand Central Dispatch getting value from block in dispatch_async

I'm using below code to download some data from the web. Am I right that I need to retain the data like I have done? Also the NSLog statement from inside the block shows that the array has been populated, but when I run the NSLog outside the block the arrays show as (null). How would I save the data outside dispatch_async method?
__block NSArray *downloadedCareerIds;
__block NSArray *diskCareerIds;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/* Download stuff */
downloadedCareerIds = [[CareersParser idsFrom:#"web"] retain];
diskCareerIds = [[CareersParser idsFrom:#"disk"] retain];
DLog(#"downloadedCareerIds: %#", downloadedCareerIds);
DLog(#"diskCareerIds: %#", diskCareerIds);
});
DLog(#"downloadedCareerIds: %#", downloadedCareerIds);
DLog(#"diskCareerIds: %#", diskCareerIds);
The idea of dispatch_async is that you give it a block of code to execute asynchronously, therefore giving up any control of when that code gets executed. The call to dispatch_async returns once the block has been enqueued, NOT once the block has finished executing (hence async). Therefore, the log statements inside of the block you're passing to dispatch_async will get executed, almost always, after the log statements below your call to dispatch_async.
dispatch_async is a non blocking method so it will return immediately. So when the DLog statements outside the block are called, they will mostly not have been set. Hence you don't see the values you get from the internal log statements.
If you want to act on the data within the same method, you will have to either send a blocking dispatch_sync which is pointless or you can call the methods within the block.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
....
[self doStuffWithTheArrays];
});
Once the block is executed the objects will be available provided they are instance variables or you will lose the references.

Resources