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.
Related
I using the below code to set elements in an array and return the array, the returned array is then passed to another method for more changes before again being returned.
NSMutableArray *returnArray = [[NSMutableArray alloc]init];
//call checkTP1
returnArray = [self checkTP1STD:addingTime :startToTP1 :TP1Result :nowDate :sevenHour :totalrest :returnArray];
//call check TP2
returnArray = [self checkTP2STD:addingTime :startToTP2 :TP2Result :nowDate :sevenHour :totalrest :returnArray :tp2Rest];
It is currently working as expected, my question is will it always wait for the checkTP1STD to return before executing checkTP2STD?
I have split the code into multiple methods to enable it to be more readable as i will be adding some other logic to pass different variable values to the methods,just wanted to make sure my basic idea will work.
In general: yes
Your question is curious, you seem to be concerned that checkTP1STD will return before checkTP2STD is called, but not that the calls to alloc and init will return before the call to checkTP1STD.
Are you actually intending to do asynchronous work in checkTP1STD (E.g. Using GCD or system framework methods which state they are async). If so the answer is still yes, but the call may return before all the work scheduled by checkTP1STD is complete - the very nature of asynchronous programming.
HTH
In short, yes. Code is executed in sequential order unless there's explicit calls to new threads, which you're not doing by the code you've given.
I have a function which is loading image by index in another thread using GCD .
So lets assume this :
-(void)loadMainImageToIndex:(long)index
{
NSDictionary *dic=[mainData objectAtIndex:index];
NSString *userImageUrl=[dic objectForKey:#"url"];
NSURL *userUrl=[NSURL URLWithString:userImageUrl];
[self downloadImageWithURL:userUrl completionBlock:^(BOOL succeeded, NSData *tdata)
{
if (succeeded)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
//do something here
dispatch_async(dispatch_get_main_queue(), ^
{
//do something here that uses the index argument
And i call this function 3 times :
[self loadMainImageToIndex:0];
[self loadMainImageToIndex:1];
[self loadMainImageToIndex:2];
Question is, when the first call will end the thread operation , and will got to the point :
dispatch_async(dispatch_get_main_queue()
Will he see in there index=0 , or will he see the last index was called (==2) ?
Question is, does he copy the whole function so when he finishes he can remember the argument that started the method ?
Another thing, does calling it 3 times at the same time, is a bad practice ?
Thanks.
Short version: there's no problem here. You're doing fine and it'll behave like you would expect (each block will have the correct value).
Longer version:
-(void)loadMainImageToIndex:(long)index
Every call to this method will push a fresh copy of index onto the stack. It will be popped (destroyed) when the method returns. Even if this method is called many times in parallel (on different threads), each will have its own copy of index on its own stack. Local variables and arguments are private to a each call of a method or function.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
The creation of a block here "captures" (copies) all the variables that it discovers within the block. That includes index because it's used by:
dispatch_async(dispatch_get_main_queue(), ^
So, there's no problem here. Your block that is sent to the main queue will have its own copy of index, which it made at the time the block was created. The enclosing block also made a copy of index at the time it was created, and the method made a copy of the value that was passed to it as index.
Note that "when a block is created" is the point at which the ^{} is evaluated, not the point that dispatch_ functions are called. Those functions accept a block, they don't create the block. It is completely legal (and common) to create a block and store it in a variable and later pass that block to something else. The block will capture (copy) its variables at the point that it's created. This concept is called a closure.
I was looking into iOS NUI Framework source code. I spotted the following line of codes but I couldn't figured out how it worked
- (void)override_didMoveToWindow
{
if (!self.isNUIApplied) {
[self applyNUI];
}
[self override_didMoveToWindow];
}
Just to be clear, they swizzled out the original implementation of DidMoveToWindow with this method in order to apply the class/style at run time. What confused me was that the function above never caused any infinite loop.
This may help: http://darkdust.net/writings/objective-c/method-swizzling
The swizzled method is actually exchanged with the original. So when the original method is called the swizzled method has already exchanged the implementation. And calling the "swizzled method" override_didMoveToWindow method will call the original function.
Comment the line
//[self override_didMoveToWindow];
works for me
It looks like not a loop because it appears the author assumes that [self applyNUI] always changes the state so that self.isNUIApplied becomes == YES
Is it possible to check if a particular method is being executed at a particular point of time on iOS ?
For example, I want to know if the method sampleMethod is being run at 1 minute after the app starts executing?
Can't you use _cmd for that?
NSLog(#"Method name = %#", NSStringFromSelector(_cmd));
Using breakpoints and/or the NSLog(NSString) function inside your mehthods.
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
}
}