If I have this method:
-(void) methodName
{
action1;
action2;
[self methodName];
}
I want the [self methodName] call to be done only once, therefore the method to be called only twice consecutively. Can this be done? Not sure where in the docs I should be looking.
Whenever method 'methodName' is called, then when action1 and action2 are done, it should call itself again, but only once. The way it is done in the sample code I have written is going on forever (I am guessing).
If you mean to say only once during the entire lifetime of the application, you can use dispatch_once, like this:
-(void)methodName
{
action1;
action2;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self methodName];
});
}
If, however, you meant for the method to execute action1 and action2 twice per invocation, you have two options:
1) Wrap that functionality in another method:
- (void)executeMethod {
[self methodName];
[self methodName];
}
2) Even simpler, wrap it in a loop:
- (void)methodName {
for(int i = 0; i < 2; ++i) {
action1();
action2();
}
//...
}
You can use static variable:
-(void) methodName
{
static BOOL called = NO;
if (called == NO)
{
called = YES;
[self methodName];
}
else
{
called = NO;
}
}
The simplest thing to do is split that in two methods:
-(void) subMethodName
{
action1;
action2;
}
-(void) methodName
{
[self subMethodName];
[self subMethodName];
}
Or to use a loop of some form or other.
(What you have in your original code is infinite recursion - not a good thing in general.)
You need to apply some logic on it. This can be using Bool Variable Or simply a count.
Take
int Count=0; //as a global variable.
Now just modify your method as follows
-(void) methodName
{
Count++;
action1;
action2;
if(Count==1)
[self methodName];
}
Related
I have the following dummy architecture: a singleton class that will receive some data, and, at some point(when returnCallback function is called), will return the data using a callback.
#interface Helper: NSObject
{
void (^_completionHandler)(int someParameter);
}
+(Helper *)getInstance;
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
#end
#implementation Helper
+(Helper *)getInstance {
static Helper *instance = nil;
#synchronized(self) {
if (instance == nil)
instance = [[self alloc] init];
}
return instance;
}
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
//do things
_completionHandler = [handler copy];
//do things
}
-(void) returnCallback
{
int result;
//do things with result
_completionHandler(result);
//nothing to follow, it just returned the result.
}
#end
Untill now I was calling the helper a single time and everything worked ok.
E.g.
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
NSLog(#"I received %d", result);
}];
But now I need to call the helper 2 times, the second one being inside of the first one.
E.g.
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
NSLog(#" Yay, I'm good %d", result);
}];
NSLog(#"They stopped retaining me:( %d", result);
}];
The problem is(as displayed in the log) that the first function callback is released from memory and I cannot access the result variable. A way to resolve that is to keep 2 variables of the callbacks(one with the current one, one with the old one), but what if I'll need the 3rd one? I tried to build an NSMutableArray with the blocks references. But I had to remove them aswell, and I didn't figure out how.(they get copied inside Helper class, so I don't have a reference to that copied object inside the "Testing" class, do I?)
The above code isn't tested as this is more of an architecture-based question. I will however test it and edit the message asap if there are any errors.
Due to the way you have it designed, you can only have one active operation. If you ever try to execute more operations than one at the time, unexpected stuff happens (as in your example).
There is an established pattern for doing stuff like this - take a look at NSOperation and NSOperationQueue, e.g. here
In our app, we use singletons in several locations, and recently I went through and added #synchronized commands to all of the singleton methods to ensure that they are thread-safe. My question is what the difference is between calling this:
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
#synchronized(receiverCache)
{
if (!receiverCache )
receiverCache = [[RLReceiver alloc] init];
return receiverCache;
}
}
In this case I synchronize the static instance of the class RLReceiver, but I have also seen (and the compiler surprisingly allows) this as well:
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
#synchronized(self)
{
if (!receiverCache )
receiverCache = [[RLReceiver alloc] init];
return receiverCache;
}
}
Where the synchronize is on self. This confuses me a little, since this method is a class method, and there shouldn't even be a self inside this scope of this method. Can anyone shed some light on what the difference is between the static variable and self is in this context, and how there would even be a self inside of a class method?
According to Apple Doc: "The object passed to the #synchronized directive is a unique identifier used to distinguish the protected block. If you execute the preceding method in two different threads, passing a different object for the anObj parameter on each thread, each would take its lock and continue processing without being blocked by the other. If you pass the same object in both cases, however, one of the threads would acquire the lock first and the other would block until the first thread completed the critical section."
// Apple example:
- (void)myMethod:(id)anObj
{
#synchronized(anObj)
{
// Everything between the braces is protected by the #synchronized directive.
}
}
In your case, how Hot Licks says the problem is the first launch. Your object doesn`t exist in the first launch and the synchronized doesn't work properly. If you try:
[1]
+(RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
#synchronized(receiverCache)
{
if (!receiverCache ) {
receiverCache = [[RLReceiver alloc] init];
}
for (int i=0; i<100; i++) {
NSLog(#"Numbers in order i %i",i);
}
return receiverCache;
}
}
and [2]
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
#synchronized(self)
{
if (!receiverCache ) {
receiverCache = [[RLReceiver alloc] init];
}
for (int i=0; i<100; i++) {
NSLog(#"Numbers in order i %i",i);
}
return receiverCache;
}
}
From another object calling in the first time something like that:
dispatch_async(dispatch_queue_create("OtherQueue", 0), ^{
RLReceiver *rece= [RLReceiver getReceiver];
});
RLReceiver *receSorF = [RLReceiver getReceiver];
You could see how in the [1]case the numbers are mixed and synchronized is not working. In the [2] case one count wait the other.
We can use the object when we synchronize code in a existed object, in other case class name.
Thanks #HotLicks.
In C# you can create a delegate method, assign it to a variable or pass it into a method as if it were a variable. For example:
public delegate int Lookup(String s);
//...
public static int Evaluate(String exp, Lookup variableEvaluator)
{
//...
}
I heard that in C you can create a pointer to any method and then pass that pointer to a method.
Can anyone give me a simple example of doing that in Objective-C? Of course, I can create an object with a singe method and pass that object into a method. But I am curious if there is a way of doing that similar to that of C# or C.
Lots of ways.
One: the good. Use blocks (closures, lambda calculus, however you call it):
typedef void (^MyCallback)();
- (void)callTheCallback:(MyCallback)blockToInvoke
{
blockToInvoke();
}
MyCallback cb = ^{
NSLog(#"I was called! :D");
};
[self callTheCallback:cb];
Two: the bad. Grab a pointer to the method function itself and call that. (Warning: if you use this approach, I'll sue you.)
- (void)callTheCallback:(IMP)funcPtrToCall withObject:(id)obj selector:(SEL)sel
{
funcPtrToCall(obj, sel);
}
- (void)someCallbackMethod
{
NSLog(#"I was called! :D");
}
IMP implemt = [[self class] instanceMethodForSelector:#selector(someCallbackMethod)];
[self callTheCallback:implemt withObject:self selector:#selector(someCallbackMethod)];
Three: the ugly. Use a delegate:
- (void)delegateMethodOfSomeObject:(SomeObject *)obj
{
NSLog(#"I was called! :D");
}
SomeObject *obj = [[SomeObject alloc] init];
obj.delegate = self;
[obj makeThisObjectSomehowCallItsDelegateThatIsCurrentlySelf];
Two quick thoughts come to mind.
The short answer is called "blocks", but it's lower level than is probably recommended for what you need.
The "cleaner" solution (read: higher level) is to pass two params: and object (called "target") and a selector (called "action"). This is a very common pattern in Objective-C, so I'll only demonstrate this one. If you are interested in the blocks idea, check out this doc.
Essentially, the object should be passed as an id, and the selector as a SEL, for which we have the handy #selector() construct:
-(void) doThingWithTarget:(id) targetObj action:(SEL) actionSel {
if([targetObj respondsToSelector:actionSel]) {
[targetObj performSelector:actionSel withObject:self];
}
}
// ...
[thatOtherObject doThingWithTarget:self action:#selector(myMethod:)];
// ... where
-(void) myMethod:(id) sender {
// sender is the calling object, or should be by contract.
}
Objective C uses selectors. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocSelectors.html
I have a simple class with two ivars, a NSMutableArray and a BOOL. Objects of this class are able to shuffle elements in the array when they are sent the startShuffling message. They do so until they receive the stopShuffling message.
To make it work, the startShuffling method set the boolean to YES, and then dispatch the block of code that shuffles (while(self.isShuffling) { //... } on a concurrent queue. The stopShuffling set the boolean to NO, so that the shuffling process will terminate on the next loop turn.
Here is the interface :
#interface MyClass : NSObject <NSCoding> {
#private
NSMutableArray *elements_;
__block BOOL isShuffling_;
}
#property(readonly) BOOL isShuffling;
-(void)startShuffling;
-(void)stopShuffling;
#end
And the implementation :
#implementation MyClass
#synthesize isShuffling = isShuffling_;
-(void)startShuffling {
if(self.isShuffling) {
return;
}
isShuffling_ = YES;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
while(isShuffling_) {
// code that shuffles, one element by turn
NSUInteger elementIndex = arc4random() % [elements_ count];
id c = [[elements_ objectAtIndex:elementIndex] retain];
[elements_ removeObjectAtIndex:elementIndex];
[elements_ insertObject:c atIndex:[elements_ count]];
[c release];
}
});
}
-(void)stopShuffling {
isShuffling_ = NO;
}
#end
My class conforms to NSCoding protocol and I don't want to abort encoding even if the object is shuffling. Instead I want my object to stop shuffling and then encode itself. So I have written this encoding method :
-(void)encodeWithCoder:(NSCoder *)aCoder {
if(self.isShuffling) {
[self stopShuffling];
}
[aCoder encodeObject:elements_ forKey:kIVPCodingKeyMyClassElements];
}
Finally, here my question.
I think it is possible for the encodeObject:forKey: method to get called while the shuffling loop terminates its last turn (maybe I'm wrong ?).
Is there any way I can make encodeObject:forKey: method get called after wait for the shuffling loop last turn to terminate ?
Yes, the the shuffle code may still be running when the encodeObject:forKey: method is called.
In general, you don't want to dispatch some random block off onto a queue that executes for a really long time, potentially forever. You want to break up the work into blocks of work. And there-in lies your answer.
Something like:
- (void)shuffleAndCheck
{
if (stillShuffling) {
dispatch_async(globalConcurrentQueue, ^{
dispatch_apply(shuffleQueue, ^{... shuffle one card code ...});
});
dispatch_async(shuffleQueue, ^{ [self shuffleAndCheck]; });
}
}
- (void) startShuffling
{
if (stillShuffling) return;
stillShuffling = YES;
[self shuffleAndCheck];
}
- (void) stopShuffling
{
stillShuffling = NO;
dispatch_async(shuffleQueue, ^{ ... encode stuff here ... });
}
Or something.
#implementation ThisObject
-(void)start {
SomeOtherObject *someOtherObject = [SomeOtherObject alloc];
[someOtherObject doSomethingAndCallThisFunctionWhenUrDone:myCallBackFunction :self];
}
-(void)myCallBackFunction {
// :)
}
Basically, how can I make this work?
There are four ways to make a callback:
Function Pointer You can do a function pointer if you really want, but it's not recommended. It's done the same way you would do it in C. The problem is you can't use a function pointer to an Objective-C method. It looks something like this:
void callback(/* Some args */) {
// Some callback.
}
- (void)doSomethingAndCallThisFunctionWhenDone:(void(*)(/* Some args */))func {
// Do something.
if (func)
func(/* Some args */);
}
- (void)start {
[self doSomethingAndCallThisFunctionWhenDone:&callback];
}
Selectors You can use -performSelector:. It looks like this:
- (void)doSomethingAndCallTarget:(id)target withSelector:(SEL)sel {
// Do something.
[target performSelector:sel];
}
- (void)start {
SomeOtherObject * someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingAndCallTarget:someOtherObject withSelector:#selector(MyCallback)];
}
Delegates Use a delegate. This is similar to UITableViewDelegate/UITableViewDataSource. See the Apple docs here. You might do it like this:
- (void)doSomethingDelegate:(id<MyCallbackObject>)delegate {
[delegate retain];
// Do something.
[delegate performMyCallback]; // -performMyCallback must be declared in the MyCallbackObject protocol and implemented by SomeOtherObject.
[delegate release];
}
- (void)start {
id<MyCallbackObject> someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingDelegate:someOtherObject];
[someOtherObject release];
}
Blocks The preferred way for callbacks is to use blocks. They are only available for iOS 4.0+ or Mac OS X 10.6+. It looks something like this:
- (void)doSomethingAndCallThisBlockWhenDone:(void(^)(/* Some args */))block {
[block copy];
// Do something.
if (block)
block(/* Some args */);
[block release];
}
- (void)start {
[self doSomethingAndCallThisBlockWhenDone:^void(/* Some args */){ // Return type and arguments may be omitted if you don't have any.
// Your callback
}];
}
As you can see with the block, it's easier to read and your callback is inline with your code. This is especially nice so you don't have to hunt it down. There are many more benefits of blocks, but I couldn't possibly cover them all here.
One last thing, if you use a block, you will want to use a typedef so you don't have to type obscure block types like void(^)(/* Some args */) all the time. The typedef could look like this:
typdef void(^MyCallback)(/* Some args */);
Then, you can declare your method like this:
- (void)doSomethingAndCallThisBlockWhenDone:(MyCallback)block;
Update:
I have shown more detail of how to implement the different techniques (see above).
Are you talking about this?
-(void)callSomePassedSelector:(SEL)callbackSelector {
[someObjectThatRespondesToThisSelector performSelector:callbackSelector];
}
I assume you want to store it and call it later, but this should give you all the needed information about how to pass and call it. There are other methods to invoke the selector, see more here
im a bit confused about what you talking about but is this it?
[self performSelector:#selector(myCallFunction)];