Using dispatch_after in SpriteKit, passing multiple arguments from another class - objective-c

I was using performSelector to generate SKSpriteNodes after a random period of time, until a lot of people told me it was better to use dispatch_after.
What I have understood is that I need to create a function that will have the dispatch_after and then there it will point to another function that I want to do repeatedly. But this creates a problem to me. I need to pass two arguments to the method that creates the SKSpriteNodes from another class.
If I've understood correctly, in that class I need to call the method that has the dispatch_after so that it can perform the action repeatedly. Then, how would I do all of this? Do I need to pass those arguments multiple times? Also, I cannot addChild:the method that has the dispatch_after because it does not return a SKSpriteNode (the one that creates them does indeed). So, I'm really confused.

Related

Objective-C: use NSThread with a function or block, without need for an additional object

I have an Objective-C app where I need to run a function in a separate thread. This function will run continuously with a run loop and will need to be canceled at a later date, so I think the right thing to use is NSThread. I don't think this is an appropriate time to use Grand Central Dispatch. (Do correct me if I'm wrong.)
NSThread requires me to allocate and maintain a separate object with a method that will be executed in the new thread, e.g. [[NSThread alloc] initWithTarget:someObject selector:#selector(runThread) object:nil]
Granted this may seem like a trifling complaint, but is there any way for me to start a thread like this without needing this separate object? I'd like to just use a C-style function or a block.
The documentation is organized a bit oddly, but NSThread has -initWithBlock: and +detachNewThreadWithBlock:.

what was the second parameter in "id (*IMP)(id, SEL, ...) " used for?

my question as the title says.obviously, the first parameter was used for this pointer , in some taste of c++.what about the second one? thak you.
The signature of objc_msgSend() is:
id objc_msgSend(id self, SEL op, ...);
Every method call is compiled down to a call to this function. I.e., if you call:
[anArray objectAtIndex:42];
That will be compiled as if it were:
objc_msgSend(anArray, #selector(objectAtIndex:), 42);
Now, to your question, why do methods get compiled down to a function that has the SEL as the second argument. Or, more specifically, why is this method:
- (id)objectAtIndex:(NSUInteger)index;
Exactly equivalent to this C function:
id object_at_index(id object, SEL _cmd, NSUInteger index);
The answer is speed speed speed.
Speed
Specifically, by doing this, then objc_msgSend() never has to rewrite the stack frame* and it can also use a tail call optimization to jump directly to the method invocation. This is the same reason why you never see objc_msgSend() in backtraces in the debugger (save for when you actually crash/break in the messenger).
objc_msgSend() uses the object and the _cmd to look up the implementation of the method and then, quite literally, jumps to that implementation.
Very fast. Stack frame untouched.
And, as others have stated, having _cmd around in the method implementation can be handy for a variety of reasons. As well, it also means that the messenger can do neat tricks like proxy support via NSInvocation and the like.
*rewriting the stack frame can be insanely complex and expensive. Some of the arguments might be in registers some of the time, etc... All architecture dependent ABI nastiness. One of the biggest challenges to writing things like imp_implementationWithBlock() was figuring out how to do so without touching the stack because doing so would have been too slow and too bloated to be viable.
The purpose of having the second parameter contain the selector is to enable a common dispatch mechanism. As such, the method dispatch code always expects the second parameter to be the selector, and dispatches based on that, or follows the inheritance chain up, or even creates an NSInvocation and calls forwardInvocation:.
Generally, only system-level routines use the selector argument, although it's rather nice to have it when you hit an exception or are in the debugger trying to figure out what routine is giving you difficulties if you are using forwardInvocation
From the documentation:
Discussion
This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
In Objective-C when you call a method you need to know the target, the selector and the eventual arguments. Let's suppose that you are trying to do this manually: how can you know which method to call if you don't know the selector? Do you call some random method? No, you call the right method because you know the method name.

sequential methods execution obj-c

Very beginner obj-c question.
My task is to do simple sequence when view loads:
pause 2 secons
method1 execution
pause 2 seconds
method2 execution
pause 2 seconds
method3 execution
I write this code for iOS5+ so blocks or other features can be used. I tried
[NSThread sleepForTimeInterval:x];
to make the pauses between methods executions, but three pauses added to one and I have one big pause, so it's wrong piece.
How to do this in right way?
Sleeping an NSThread is never the right way to handle timed method execution. You want NSTimer, which you can set to either fire the same method after two seconds (then have that method determine which selector to perform next), or have three timers set to fire two seconds after each other, each calling a different method.
You could use performSelector:withObject:afterDelay:, or as CodaFi said, an NSTimer. Either method allows to to pass an object to the method, and that object could be an array or dictionary, if you need to pass multiple arguments.
I'd chain the methods:
call 1. method and make it call 2.
method should call 3.
should proceed to 4.
...

Removing Object With Timer

I have two NSMutableArrays, collectables and collectableViews.
My app consists of a character moving around and gathering collectables (coins, apples, bananas, etc) for points...
I would like the collectables to disappear after a certain amount of time.. however, I am confused as to where to put an NSTimer to not disrupt Model/View/Controller design.
For example, If I put an individual timer in each model, the model doesn't know of the view and cannot remove the view..
If I put the NSTimer in the controller, I would need to make another array consisting of all the collectables on the screen, in order of which one expires first. The timer's method would fire every second and remove each collectable when they are due.
Is there an easier, better way to do this?
Most games model this kind of 'state-monitoring' using one or more game clocks. You can do something like this:
Create a data structure containing a duration time, function
pointer, and array of object variables. For this example let's call
it DecayEvent.
Create a static, mutable array of DecayEvent's in your front (main)
controller, with some nice accessor methods
Choose an appropriate event processing interval. It needs to be
large enough to process what you think the maximum number of events
will be, but small enough not to retard user experience.
Create a method on your front controller that will process through
the array of decay events. Every time the method is called it will
iterate the array and decrement the event's duration time by the
event processing interval. If the decay events duration falls below
zero then 'fire the event' (basically, trigger its callback function
in another thread, with the callback arguments).
Create an NSTimer in your main thread. Set it to call your
processing method at every event processing interval.
You will have to tweak quite a bit to get everything working the way you want, but the steps above will generally work.
Good luck!
Your current situation tends that you should keep timer in your controller because controller has access to each data modal and views you can access arrays too. also another approach is to use NSNotificationCenter. First try and if that doesn't work then let us know.

How to execute #selector method 1st in Objective-C/

How to make the #selector method execute 1st and then AuthenticateMobileServer in the below startement in Objective-C?Because AuthenticateMobileServer method is dependent on Handler logic.
[mobile_Obj AuthenticateMobileServer:self action:#selector(Handler:)];
Please help.
Thank You.
#selector(...) doesn't call the method. How does the AuthenticateMobileServer:action: method normally work? We need more information.
Perhaps I'm lost, but why not just invoke it yourself first?
[self Handler:...];
[mobileObj AuthenticateMobileServer:self action:#selector(PostHandler:)];
As a note, method names in Objective-C generally follow lowerCamelCase convention.
What you're doing is sending a message to mobile_Obj to execute the method AuthenticateMobileServer. The selector is passed along as an argument - but that doesn't mean the method it points to will actually be called. Whether this happens or not depends on what logic is working in AuthenticateMobileServer.
So, if AuthenticateMobileServer depends on whatever value "Handler" returns, you need to instantiate a class that implements "Handler" (or keep a reference to an existing instance and use it) right at the beginning of AuthenticateMobileServer's implementation, call "Handler" on it and grab the result.