I have a set of animations that need to operate sequentially with various checking done at each step. Because the size of the set is determined at run time, I expected to utilize a recursive call... but I am having trouble getting it to function within the 'block' paradigm.
The result is an EXEC_BAD_ACCESS regardless of whether I predeclared the block using
__block void (^myBlock)(BOOL) = ^(BOOL finished){ if (finished) [self nextStep];};
or not, as seen in the following code snippet. Upon debugging, it appears that the 'self' variable is indeed valid.
NSEnumerator* stepEnumerator;
-(void) mainRoutine {
stepEnumerator = [myArray objectEnumerator];
[self nextStep];
}
-(void) nextStep {
id obj;
if ((obj = [stepEnumerator nextObject])) {
// Do my checking at each location
....
// we have another spot to move to
[UIView animateWithDuration:animationDuration
animations:^{self.frame = newFrame;}
completion:^(BOOL finished){ if (finished) [self nextStep];}];
}
}
else {
// we are done, finish house cleaning
}
}
Any help is greatly appreciated.
Thanks!
The answer to the question posed is, yes, recursive calls within a block completion are valid.
#BillBrasky brought up a good point about the block losing scope. I do not know enough to say if this is required or not as I have not found it to be an issue with my situation. Everything appears to work correctly for me on each successive iteration through my recursive function.
The core issue with the code as I originally wrote it and submitted it is the use of the FastEnumerator. This is DEFINITELY lost when you leave the current function and venture out into another event loop / new section of the stack frame. I realized as I thought more about it that there is probably quite a bit going on behind the scenes to make FastEnumeration work and it is quite logical that leaving the method would destroy the setup.
As a fix, I replaced the NSEnumerator with a simple integer that I then increment each time through the recursive function. I am not a big fan of this as it could lead to Out of Bounds style issues where as the FastEnumerator will not, nor will for (obj in array), but I don't know of another solution. I think I will post that as a separate question...
Corrected code:
int index;
-(void) mainRoutine {
index = 0;
if (index < [myArray count]) {
[self nextStep];
}
}
-(void) nextStep {
// obtain the object from the array
id obj = [myArray objectAtIndex:index++];
// do my checking on the object
...
[UIView animationWithDuration:animationDuration
animations:^{self.frame = [view frame];}
completions:^(BOOL finished) {
if (finished && index < [myArray count]) {
[self nextStep];
}
else {
// We are done, clean up
...
}
}];
}
Thanks again #BillBrasky, you helped point me down the correct path to resolve this. I was too focused on the recursion and my quick analysis of my 'self' object looked fine because everything except for one item was fine. Couple that with the debugger breaking on the block, not the actual offending line and who knows how long I would have been staring at the code without seeing the real issue.
Cheers.
I'm new to blocks too, but I just got done with a similar issue. In my case, the EXEC_BAD_ACCESS was caused because the block had gone out of scope. I suspect that sometime in your 2nd recursion, the block gets created with an odd stack frame because it's executing inside another block.
My solution was to keep the blocks in a property marked copy, e.g.
#property (nonatomic,copy) BOOL (^callback)(DownloadProgress*);
This ensures that everything is retained in a copy in case the original block object goes out of scope and is GC'd.
Related
I'm trying to speed up my app search , it get lags when there is a lot of data.
so i'm trying to split search Predicate on UI by using dispatch_async not dispatch_sync cause no different if I use it.
The problem is when i use dispatch_async, the app crash sometimes because [__NSArrayI objectAtIndex:]: index "17" beyond bounds.
I now this happened because lets say the first one still work and reload the tableView and continue search will change the array size depend on result so in this case "CRASH" :(
this is my code:
dispatch_async(myQueue, ^{
searchArray = [PublicMeathods searchInArray:searchText array:allData];
} );
if(currentViewStyle==listViewStyle){
[mytable reloadData];
}
and i've tried this :
dispatch_async(myQueue, ^{
NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
dispatch_sync(dispatch_get_main_queue(), ^{
searchArray = tmpArray;
[mytable reloadData];
});
});
but in this case the lags still there.
Update -1- :
The search Predicate takes just 2ms :) after hard work :)
but the keyboard still lags when the user searches, so the only thing I do after get result is reload table "change in UI" this what I think make it lags,
So what I search for split this two operation "typing on keyboard & refresh UI".
Update -2- :
#matehat https://stackoverflow.com/a/16879900/1658442
and
#TomSwift https://stackoverflow.com/a/16866049/1658442
answers work like a charm :)
If searchArray is the array that is used as table view data source then this array must
only be accessed and modified on the main thread.
Therefore, on the background thread, you should filter into a separate temporary array first. Then you assign the temporary array to searchArray on the main thread:
dispatch_async(myQueue, ^{
NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
dispatch_sync(dispatch_get_main_queue(), ^{
searchArray = tmpArray;
[mytable reloadData];
});
});
Update: Using a temporary array should solve the crash problem, and using a background thread helps to keep the UI responsive during the search. But as it turned out in the discussion, a major reason for the slow search might be the complicated search logic.
It might help to store additional "normalized" data (e.g. all converted to lower-case, phone numbers converted to a standard form, etc ...) so that the actual search can be done with
faster case-insensitive comparisons.
One solution might be to voluntarily induce a delay between searches to let the user type and let the search be performed asynchronously. Here's how:
First make sure your queue is created like this :
dispatch_queue_t myQueue = dispatch_queue_create("com.queue.my", DISPATCH_QUEUE_CONCURRENT);
Have this ivar defined in your class (and set it to FALSE upon initialization):
BOOL _scheduledSearch;
Write down this macro at the top of your file (or anywhere really, just make sure its visible)
#define SEARCH_DELAY_IN_MS 100
And instead of your second snippet, call this method:
[self scheduleSearch];
Whose implementation is:
- (void) scheduleSearch {
if (_scheduledSearch) return;
_scheduledSearch = YES;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)((double)SEARCH_DELAY_IN_MS * NSEC_PER_MSEC));
dispatch_after(popTime, myQueue, ^(void){
_scheduledSearch = NO;
NSString *searchText = [self textToSearchFor];
NSArray *tmpArray = [PublicMeathods searchInArray:searchText array:allData];
dispatch_async(dispatch_get_main_queue(), ^{
searchArray = tmpArray;
[mytable reloadData];
});
if (![[self textToSearchFor] isEqualToString:searchText])
[self scheduleSearch];
});
}
[self textToSearchFor] is where you should get the actual search text from.
Here's what it does :
The first time a request comes in, it sets the _scheduledSearch ivar to TRUE and tells GCD to schedule a search in 100 ms
Meanwhile any new search requests is not taken care of, because a search is going to happen anyway in a few ms
When the scheduled search happens, the _scheduledSearch ivar is reset to FALSE, so the next request is handled.
You can play with different values for SEARCH_DELAY_IN_MS to make it suit your needs. This solution should completely decouple keyboard events with workload generated from the search.
First, a couple notes on the code you presented:
1) It looks as if you're likely queuing up multiple searches as the user types, and these all have to run to completion before the relevant one (the most recent one) updates the display with the desired result set.
2) The second snippet you show is the correct pattern in terms of thread safety. The first snippet updates the UI before the search completes. Likely your crash happens with the first snippet because the background thread is updating the searchArray when the main thread is reading from it, meaning that your datasource (backed by searchArray) is in an inconsistent state.
You don't say if you're using a UISearchDisplayController or not, and it really doesn't matter. But if you are, one common issue is not implementing - (BOOL) searchDisplayController: (UISearchDisplayController *) controller shouldReloadTableForSearchString: (NSString *) filter and returning NO. By implementing this method and returning NO you are turning off the default behavior of reloading the tableView with each change to the search term. Instead you have opportunity to kick off your asynchronous search for the new term, and update the UI ([tableview reloadData]) only once you have new results.
Regardless of whether you're using UISearchDisplayController you need to take a few things into consideration when implementing your asynchronous search:
1) Ideally you can interrupt a search-in-progress and cancel it if the search is no longer useful (e.g. the search term changed). Your 'searchInArray' method doesn't appear to support this. But it's easy to do if your just scanning an array.
1a) If you can't cancel your search, you still need a way at the end of the search to see if your results are relevant or not. If not, then don't update the UI.
2) The search should run on a background thread as to not bog down the main thread and UI.
3) Once the search completes it needs to update the UI (and the UI's datasource) on the main thread.
I put together sample project (here, on Github) that performs a pretty inefficient search against a large list of words. The UI remains responsive as the user types in their term, and the spawned searches cancel themselves as they become irrelevant. The meat of the sample is this code:
- (BOOL) searchDisplayController: (UISearchDisplayController *) controller
shouldReloadTableForSearchString: (NSString *) filter
{
// we'll key off the _currentFilter to know if the search should proceed
#synchronized (self)
{
_currentFilter = [filter copy];
}
dispatch_async( _workQueue, ^{
NSDate* start = [NSDate date];
// quit before we even begin?
if ( ![self isCurrentFilter: filter] )
return;
// we're going to search, so show the indicator (may already be showing)
[_activityIndicatorView performSelectorOnMainThread: #selector( startAnimating )
withObject: nil
waitUntilDone: NO];
NSMutableArray* filteredWords = [NSMutableArray arrayWithCapacity: _allWords.count];
// only using a NSPredicate here because of the SO question...
NSPredicate* p = [NSPredicate predicateWithFormat: #"SELF CONTAINS[cd] %#", filter];
// this is a slow search... scan every word using the predicate!
[_allWords enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
// check if we need to bail every so often:
if ( idx % 100 == 0 )
{
*stop = ![self isCurrentFilter: filter];
if (*stop)
{
NSTimeInterval ti = [start timeIntervalSinceNow];
NSLog( #"interrupted search after %.4lf seconds", -ti);
return;
}
}
// check for a match
if ( [p evaluateWithObject: obj] )
{
[filteredWords addObject: obj];
}
}];
// all done - if we're still current then update the UI
if ( [self isCurrentFilter: filter] )
{
NSTimeInterval ti = [start timeIntervalSinceNow];
NSLog( #"completed search in %.4lf seconds.", -ti);
dispatch_sync( dispatch_get_main_queue(), ^{
_filteredWords = filteredWords;
[controller.searchResultsTableView reloadData];
[_activityIndicatorView stopAnimating];
});
}
});
return FALSE;
}
- (BOOL) isCurrentFilter: (NSString*) filter
{
#synchronized (self)
{
// are we current at this point?
BOOL current = [_currentFilter isEqualToString: filter];
return current;
}
}
i believe your crash is indeed solved by the embedding of the display of the UI element for which searchArray is the backing element in a call to GrandCentralDispatch inside of the other call (as you show in your updated original post). that is the only way to make sure you are not causing the elements of the array to change behind the scenes while the display of the items associated with it is taking place.
however, i believe if you are seeing lag, it is not so much caused by the processing of the array at 2ms or the reload that takes 30ms, but rather by the time it takes GCD to get to the internal dispatch_sync call on the main queue.
if, by this point, you have managed to get the processing of your array down to only 2ms in the worst case (or even if you've managed to get it down to less than 30ms, which is about the time it takes to process a frame in the main run loop at 30 fps), then you should consider abandoning GCD altogether in your effort to process this array. taking 2ms on the main queue to process your array is not going to cause any buggy behavior.
you may have lag elsewhere (i.e. if you are incrementing search results by trying to go out to the net to get the results, you may want to do the call and then process the response on your separate dispatch queue), but for the times you are talking about, this bit of processing doesn't need to be split out onto separate queues. for any hard-core processing that takes over 30ms, you should consider GCD.
I suspect your problem is that allData is shared between the main queue and the background queue. If you make a change in allData on the main queue, that may shorten allData in the background queue, causing an index that used to be valid to become invalid.
It's also possible that the problem is not allData itself, but some array within the objects in allData. Try setting a breakpoint on exceptions (in Xcode, open the Breakpoints source list, click the plus button at the bottom, and choose "Add Exception Breakpoint...") so you can see exactly where the error occurs.
In either case, you have two possible solutions:
Copy the offending object before using it in the search. This protects the background queue from changes in the main queue, but depending on what you need to copy, it may be difficult to get the changes back into the UI—you might have to match the copies back to their originals.
Use a lock (like #synchronized) or a per-object queue to ensure only one queue is using the object at a time. NSManagedObjectContext uses the latter approach for its -performBlock: and -performBlockAndWait: methods. It may be a little tricky to do this without blocking the main queue, though.
Try to modify your functions the next way:
function prototype;
- (void)searchInArray:searchText array:allData complete: (void (^)(NSArray *arr)) complete;
function itself
- (void)searchInArray:searchText array:allData complete: (void (^)(NSArray *arr)) complete {
NSArray * array = [NSArray new];
// function code
complete(array)//alarming that we have done our stuff
}
and when you are calling this function
dispatch_queue_t searchQueue = dispatch_queue_create("com.search",NULL);
dispatch_async(searchQueue,^{
[PublicMeathods searchInArray:searchText array:allData complete:^(NSArray *arr) {
searchArray = arr;
dispatch_async(dispatch_get_main_queue(), ^{
[myTable reloadData];
});
}];
});
Hope it will help you)
I found a simple solution with the same spirit of the solution presented by Matehad (wait some time and perform a search only if the user doesn't input anything else). Here it is:
Declare 2 global counters and a global string:
int keyboardInterruptionCounter1 = 0, int keyboardInterruptionCounter2 = 0 and NSString *searchTextGlobal
On the searchBar function do this:
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
keyboardInterruptionCounter1++;
searchTextGlobal = searchText;//from local variable to global variable
NSTimeInterval waitingTimeInSec = 1;//waiting time according to typing speed.
//waits for the waiting time
[NSTimer scheduledTimerWithTimeInterval:waitingTimeInSec target:self selector:#selector(timerSearchBar:) userInfo:nil repeats:NO];
}
-(void)timerSearchBar:(NSTimer *)timer{
keyboardInterruptionCounter2++;
// enters only if nothing else has been typed.
if (keyboardInterruptionCounter2 == keyboardInterruptionCounter1) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
//do the search with searchTextGlobal string
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
});
}
}
Explanation: The search is performed only if both counters are the same, this only happens if the user has typed and waited .52 sec without typing anything else. Instead, if the users types fast enough, then no query is done. The solution can be done with or without threading.
Martin R has posted a correct answer. The only thing to point out that instead of
dispatch_sync(dispatch_get_main_queue()
it should be
dispatch_async(dispatch_get_main_queue()
The complete code in Swift would be:
let remindersFetcherQueue = dispatch_queue_create("com.gmail.hillprincesoftware.remindersplus", DISPATCH_QUEUE_CONCURRENT)
dispatch_sync(remindersFetcherQueue) {
println("Start background queue")
estore.fetchRemindersMatchingPredicate(remindersPredicate) {
reminders in
// var list = ... Do something here with the fetched reminders.
dispatch_async(dispatch_get_main_queue()) {
self.list = list // Assign to a class property
self.sendChangedNotification() // This should send a notification which calls a function to ultimately call setupUI() in your view controller to do all the UI displaying and tableView.reloadData().
}
}
}
I have a NSString called fontType
and I am trying to have a custom setter for it:
- (void) setFontType:(NSString *) fType
{
if (self.fontType != fType){
[fontType release];
self.fontType = [fType retain];
//some more custom code
}
}
Is there any issue with this?
A few things that stand out for me:
do not use self. inside of custom accessors. access the variable directly
it's better use copy semantics for properties of a type that has a
mutable subtype
be careful with whatever is // some more custom code
My personal style preferences are like so:
-(void)setFontType:(NSString *)fontType_ {
if (fontType == fontType_) return; // get out quick, flatten the code
[fontType release];
fontType = [fontType_ copy];
// some more code
}
Cocoa with Love has a good article on this topic. It's worth a read.
When you do self.fontType = newFontType, you are doing [self setFontType:newFontType] (just with a different syntax), this means you are calling the method inside itself.
This is called recursion, but in this case, you don't have a base case in which the method will stop calling itself, so my guess is that this method will call itself until the app crashes. In short, recursion is not something you want here.
Just replace self.fontType = [fType retain] with fontType = [fType retain] (Assuming the var linked to the fontType property is called fontType as well).
PS. At the end of the question you asked
Is there any issue with this?
If you didn't try this, then you shouldn't even be asking that here on StackOverflow, and if you did try it, then you should have realized that this method didn't work, so that last line is pretty meaningless. Just saying.
So here is my code:
-(void)setMovie:(NSURL *)movieLocal {
movie = movieLocal;
[self.movie retain];
...
}
And i get this error:
Potential leak of an object allocated on line 43
Line 43 is [self.movie retain];. Am i doing something wrong, and how can i get rid of this error?
There are a couple issues here:
The old value for movie is never released
'movie' and 'movieLocal' might point to the exact same object. If that is the case, you will call retain on movie/movieLocal without a subsequent balanced release call.
You might want to use the following:
-(void)setMovie:(NSURL *)movieLocal {
if (movie == movieLocal) {
return;
}
[movie release];
movie = [movieLocal retain];
//...
}
Here's the proper setter:
-(void)setMovie:(NSURL *)movieLocal {
if (movie != movieLocal) {
[movie release];
movie = movieLocal;
[movie retain];
}
}
However, if you declared your property (in .h file):
#propert (nonatomic, retain) NSURL *movie;
and synthesized it in .m file, by #synthesize movie;, than there is no need to explicitly override the setter - the code above will be generated automatically for you. So whenever you want to set your movie you'll just call self.movie = newMovie; which will be equivalent to calling [self setMovie:newMovie];.
For more info read a section "Declared Properties" in Learning Objective-C guide.
EDIT: to explain what was wrong with your setter.
-(void)setMovie:(NSURL *)movieLocal {
movie = movieLocal; // first line
[self.movie retain]; // second line
...
}
In 1st line you are assigning movie to point to movieLocal, but you don't release old NSURL object that movie was pointing to before assignment. This was way, your causing a memory leak - you abandon memory, so it can never be relinquished back by your app. In general, abandoning memory is an easy way to get you application terminated by iOS, when objects are big and often leaked.
In 2nd line you are calling you setMovie setter again as self.movie = syntax causes the runtime to call a setter for movie property. This time it'll cause an infinite loop.
I hope my wording was clear for you and my answer helpful.
the method enumerateAttributesInRange gets a block of code and executes it for every attribute in NSAttributedString
Does it call the bock asynchronously?
When The following method gets called twice in a row really quick 1 after the othr my app gets frozen, I am wondering of it's because enumerateAttributesInRange runs the block of code asynchronously, so 2 threads are trying to modify my AttributedString at the same time.
- (void) doSomething
{
//following line works fine
[self doSomethingwithAttributedString];
//following line works fine
[self doSomethingwithAttributedString];
[self performSelector:#selector(doSomethingwithAttributedString) withObject:nil afterDelay:1];
//following crashes
[self doSomethingwithAttributedString];
[self doSomethingwithAttributedString];
}
- (void)doSomethingwithAttributedString
{
[self.attributedString enumerateAttributesInRange:_selectedRange options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:
^(NSDictionary *attributes, NSRange range, BOOL *stop) {
// Here I modify the dictionary and add it back to my attributedString
}];
}
You are modifying the attributed string while it is being enumerated. I bet this thoroughly confuses the enumerator, since the attributed string it is working on is not in the state it was in when it started enumerating. In the block, only collect the attributes, e.g. in a dictionary or array, but modify them and apply them to the string afterward, i.e. after the enumeration is finished.
In other words: don't put code that modifies the attributed string inside the block that is called during enumeration. The docs say you can modify the attributed string inside the range on which the block applies, but ISTM you must take enormous care not to go outside. I wouldn't do this.
I'm a little late, but adding [self.attributedString beginEditing]; before and [self.attributedString endEditing]; after seem to solve the crash.
We have a method in the iPhone SDK that is a delegate method. Problem is, the OS calls this method twice at the exact same time. This method does some heavy lifting so I don't want to execute the logic twice. What is a good way to detect this and prevent one of the two from running?
Forgot to mention that, it is called from different threads.
One method is a BOOL member that you set when entering the method and clear on leaving it. If the variable is set upon entry, you know it's already executing and can just return.
Assuming you're being called from multiple threads, you'll want to lock access to this critical area of checking/setting. An NSLock is good for this.
The code below has two implementations: myMethod1 which uses NSLock and myMethod2 which shows using #synchronize.
#interface MyClass : NSObject
{
NSLock* theLock;
BOOL isRunning;
}
#end
#implementation MyClass
-(id)init
{
self = [super init];
if(self != nil)
{
theLock = [[NSLock alloc] init];
isRunning = NO;
}
return self;
}
-(void)dealloc
{
[theLock release];
[super dealloc];
}
// Use NSLock to guard the critical areas
-(void)myMethod1
{
[theLock lock];
if(isRunning == YES)
{
[theLock unlock]; // Unlock before returning
return;
}
isRunning = YES;
// Do fun stuff here
isRunning = NO;
[theLock unlock];
}
// This method uses #synchronize
-(void)myMethod2
{
#synchronized(self)
{
if(isRunning == YES)
{
return;
}
isRunning = YES;
// Do stuff here.
isRunning = NO;
}
}
#end
Wow. That answer is correct, but way over-engineered. Just use #synchronized().
Foo.h:
#interface Foo
{
id expensiveResult;
}
- (void) bar;
#end
Foo.m:
#implementation Foo
- (void) bar
{
#synchronized(self) {
if (expensiveResult) return expensiveResult;
.... do expensive stuff here ....
expensiveResult = [theResult retain];
}
return expensiveResult;
}
#end
If you have multiple instances of Foo and want to guarantee exclusivity across all instances, create a global variable in +(void)initialize -- an NSString will do fine -- and #synchronized() on that.
However, your question raises a much more important question. In particular, there is never a case where the same method is going to be called twice simultaneously unless you quite explicitly configured your application to cause exactly that to happen.
The answer(s) provided sound more like a fix to a symptom and not a fix for the real problem.
Note: This is relying on expensiveResult being nil, which it will be as all iVars are nil on instantiation. Obviously, reset the ivar to nil if you want to recalculate.
simplest is to set a flag.
- (void)action {
if (flag_is_set == NO) {
flag_is_set = YES;
do stuff
flag_is_set = NO;
}
}
this is not 100% safe though as you may get some rare cases of interlocking.
If you can handle some sleeps on the thread, use a nslock
- (id)init {
theLock = [[NSLock alloc] init];
}
- (void)action {
[theLock lock];
doStuff
[theLock unlock];
}
When thread 2 comes to the lock call and thread 1 already has it, it will sit in the execution loop until the lock is released, then it will start again. If you have UI on this thread, you app will appear to freeze
Some of the given answers are acceptable solutions to the problem of multiple "producer" threads calling the same function at the same time but you might be better off figuring out why multiple threads are calling this same block of code at the same time. It could be that you are assigning this delegate to multiple event handlers or something like that. You have probably noticed that this is occurring because some shared state is being mangled or the output of the function is not correct for the "global" state at the end of the function. Putting a bandaid over the fact 2 threads are in a given function (when its clear that threading was not a primary concern when this was written) is not going to necessarily give you the right results. Threading is not trivial and shared state makes it very tricky to get right, make sure that you completely understand why this is occurring before just trying to patch over it.
That being said, if you do take the bandaid approach, its probably better to do one with a lock where every thread eventually gets to execute the function rather than having them bail out if the function is allready started because to the client code it would look like that long and "heavy-lifting" process has completed and they may check for the results.
If these calls are synchronized, so only one happens at a time, you can just have a variable on your class, called something like "initialized", which starts off false and is set when initialized:
if (!initialized) {
// handle delegated call
initialized = 1;
}
If the delegate is called from multiple threads, you need to put all this in a mutex block.
Here's how you can use objective-c locks as mutexes.
http://rosettacode.org/wiki/Mutex#Objective-C
Mutexes exist to allow mutually exclusive access to a certain block of code. Within the method you can do something like:
[methodLock lock]; //Blocks and waits until the lock is released
//...do stuff
[methodLock unlock]; //Releases the lock once the code has executed.
This will ensure that only one thread will be allowed within the //do stuff block of code.
EDIT: I read the question again; within the lock I'd check the flag to see if it's run (using a BOOL)
Use pthread_once() -- it was explicitly designed to do exactly this. The only problem is that the function you pass it can't take any arguments, so you have to use global variables to pass information to it.
If they are called at the exact same time, I guess they are called in threads?
What you can do is define a BOOL #property (called isRunning for example) with the attribute atomic (set by default). This way this property can be accessed safely from different threads, and then you can do something like:
if (isRunning)
return ;
isRunning = YES;
// ...
// Your code here
// ...
usRunning = NO;
You might also make sure that you are doing the right thing. If your method is called twice, maybe you're doing something wrong (or maybe it's normal, I don't know what you are doing ;))