I have been trying to design the Undo/Redo functionality in one of my app using NSUndoManager class and seeing some design difficulties.
In my app, I just have one method
-(IBAction) addLastBall:(Ball *)ball
So, when a user chooses a button in the UI, I add a ball object to my array list. However, I don't have any action button to remove a ball, this is the design of the UI workflow and can't be changed.
So, to implement a undo I called the following piece of code inside the addLastBall method
[undoManager registerUndoWithTarget:self selector:#selector(removeBall:) object:ball];
After doing this, removeBall method gets called with the ball object when the user tried to perform the undo. All is good for now.
But, I am not sure how to handle the redo part now, when the user tries to redo, I am not sure which method would get called, because I need to add the ball object the user just removed using the undo operation.
Any insights would be very helpful.
Thanks so much.
A redo simply performs the undo actions registered while the corresponding undo was executing. Therefore, the most straightforward solution is to simply to register an undo action in the removeBall: method.
- (void)removeBall:(Ball *)ball {
[undoManager registerUndoWithTarget:self
selector:#selector(addLastBall:)
object:ball];
...
}
Note that it is sometimes clearer to useprepareWithInvocationTarget: to register undo actions:
[[undoManager prepareWithInvocationTarget:self] addLastBall:ball];
By the way, be sure to keep the retain count of the ball above zero in the removeBall: method — the undo manager will not retain the ball for you, and if it gets deallocated, then undoing the remove will crash.
No method get's called.
The NSUndoManager simply saves the reverse of the undo operation (redo), that will be done, if the user choses redo.
It's all implemented in NSUndoManager, so you don't have to worry about it.
If you want your method to be called on redo, you should think about creating your own undo manager, but I wouldn't advice you to. It can get very complicated and besides, the NSUndoManager takes care of everything perfectly.
Related
I have a game app that, once completed, gives the option to restart. Instead of restarting each method, variable, class, etc separately, I was hoping I could just restart the whole app with the click of a button. Is there a method in swift/xcode to do this?
Thanks!
No, there's not. Best way is to set up an architecture where it's easy to reset everything because all of your state is stored in one place.
For example, inside your AppDelegate/SceneDelegate (whichever architecture you're using), you could have a GameState object that controls all aspects of the game, either by directly holding all of the properties or at least being the common ancestor of everything. Then, when it's time to reset, just create a new instance of GameState().
I'm still pretty new to scripting in Unity3D, and I'm following along with a tutorial that uses GUI.Button() to draw a button on the screen.
I am intrigued by how this function works. Looking through the documentation, the proper use of GUI.Button is to invoke the function in an if statement and put the code to be called when the button is pushed within the if statement's block.
What I want to know is, how does Unity3D "magically" delay the code in the if statement until after the button is clicked? If it was being passed in as a callback function or something, then I could understand what was going on. Perhaps Unity is using continuations under the hood to delay the execution of the code, but then I feel like it would cause code after the if statement to be executed multiple times. I just like to understand how my code is working, and this particular function continues to remain "magical" to me.
I don't know if it's the right term, but I usually refer to such system as immediate mode GUI.
how does Unity3D "magically" delay the code in the if statement until
after the button is clicked?
GUI.Button simply returns true if a click event happened inside the button bounds during last frame. Basically calling that function you are polling: every frame for every button asking the engine if an event which regards that button (screen area) is happened.
If it was being passed in as a callback function or something, then I
could understand what was going on
You are probably used to an MVC like pattern, where you pass a controller delegate that's called when an UI event is raised from the view. This is something really different.
Perhaps Unity is using continuations under the hood to delay the
execution of the code, but then I feel like it would cause code after
the if statement to be executed multiple times.
No. The function simply returns immediately and return true only if an event happened. If returns false the code after the if won't be executed at all.
Side notes:
That kind of system is hard to maintain, especially for complex structured GUI.
It has really serious performance implications (memory allocation, 1 drawcall for UI element)
Unless you are writing an editor extension or custom inspector code, I'd stay away from it. If you want to build a menu implement your own system or use an external plugin (there are several good ones NGUI, EZGUI,..).
Unity has already announced a new integrated UI System, it should be released soon.
Good question. The unity3d gui goes through several event phases, or in the documentation
Events correspond to user input (key presses, mouse actions), or are UnityGUI layout or rendering events.
For each event OnGUI is called in the scripts; so OnGUI is potentially called multiple times per frame. Event.current corresponds to "current" event inside OnGUI call."
In OnGUI you can find out which event is currently happening with >Event.current
The following events are processed link:
Types of UnityGUI input and processing events.
-MouseDown
-MouseUp,mouse button was released
-MouseMove,Mouse was moved (editor views only)
-MouseDrag,Mouse was dragged
-KeyDown, A keyboard key was pressed
-KeyUp A keyboard key was released.
-ScrollWheel The scroll wheel was moved.
-Repaint A repaint event. One is sent every frame.
-Layout A layout event.
-DragUpdated Editor only: drag & drop operation updated.
-DragPerform Editor only: drag & drop operation performed.
-DragExited Editor only: drag & drop operation exited.
-Ignore Event should be ignored.
-Used Already processed event.
-ValidateCommand Validates a special command (e.g. copy & paste).
-ExecuteCommand Execute a special command (eg. copy & paste).
-ContextClick User has right-clicked (or control-clicked on the mac).
Unity GUI has much improved lately and is quite usefull if you want to handle things programmatically. If you want to handle things visually, i recommend looking at the plugins heisenbug refers to.
If you decide to use unity gui, i recommend using only one object with ongui, and let this object handle all your gui.
Sorry if the questions is asked/answered already, or if my title is poorly worded.
I am currently writing an iPhone app, and have considered a useful tool for debugging. I would like to write a method that just prints variables and other info that I want. That part is simple and all, but I want this to be called by keystroke.
For now I have been just adding NSLog()'s to viewDidLoad or to other button methods to check if my variables are being set properly, but it's becoming tedious and the code is long so I tend to forget about some and spend a lot of time looking for them haha.
I just want one method that I can go to to write my NSLog()'s, and have that method call whenever I hit 'space' or something of that sort.
Can this be done?
Thanks!
-SF
It's pretty hard to do, you need to have a hidden text field that you keep in focus, hide the software keyboard for it, then listen on its delegate methods for changing text.
An alternative would trigger the code inside applicationWillResignActive: which gets called on application hiding, notification center showing, or double home press.
I'm trying to minimize memory usage in my app, and one of the things I'm doing is calling finish() in the onPause method (which I know is not the best way to do things). For the most part, it seems to be working well, but when the user clicks the back button from the next activity, it logically skips over the finished activity and goes back further. Is it possible to have that activity in the back stack and just get recreated if the user presses back?
No. This conclusion comes from the task and backstack documentation as well as the activity documentation and a general understanding of how a stack data structure works.
A stack data strucure only has 2 possible operations push/put, which adds something to the collection, and pop, which removes it. Stacks folow a last in first out model, or LIFO, where by last thing added - in your case an activity - is the first thing removed when pop is called.
Within the android lifecycle activities are generally popped from the stack when the back button is pressed. At that point onDestroy() is called and the activity is removed (you can verify this by overriding the onDestroy() method and logging the results if you want to check). Alternativly you can force onDestroy() to be called by calling finish() as you are. Finishing an activity effectivly does the same thing as pressing back. The activity is destroyed and must be recreated before it can be added to the stack.
For what you're trying to do the stack would have to incorporate some intermediate state in which an activity does not exist but rather something akin to a reference is held that, when moved to the top, would indicate that the corresponding activity should be recreated. Since this is not how the sack works - it only holds activities - that state cannont exist and so the result you are talking about is not possible.
Your Goal is to minimize memory usage,Just make use of activity life cycle, You can do this alternative(if you need)
-Just leave onCreate() method blank.(only do setContentView(layout))
-Override onResume();
-whatever you were doing in onCreate just copy paste to onResume().
-and In onPause(), Recycle your all bitmaps and set them to null(I think you are using Bitmaps thats why you are very cautious about it ). and remove your views.
Now what will happen, when you launch your new activity, onPause() would be called. that will remove your all bitmap and views. and when you come back, onResume() will be call.(onCreate will not be called). and that will again initialize your view and bitmaps.
No, i don't think that is possible. Once you finish the Activity it's gone. You could, however, implement and handle your own stack. On back pressed, you would just start the closed Activity again.
I am working on a large (>30k lines) event-driven app. I have a sequence of inputs that produces a bug. What I want to do is to break as soon as the final input enters my code.
Is there a general way to do that?
I understand that for any specific sequence of inputs, I can find out where that last input is going to enter my code, then set a breakpoint there. What I would like to do is take out the step of "find out where that last input enters my code." In other words, I am running the app in the simulator, and I want to set a flag somewhere that says "break the next time you are going to enter non-system Objective C code." Then I send the event that causes the problem.
I understand what you are asking, but have you tried using an Exception Breakpoint? This will basically act like an auto-inserted breakpoint on the piece of code that throws the exception. If that doesn't work for you, try a symbolic breakpoint
If you want to intercept UI events, you can try subclassing UIWindow and overriding its sendEvent: method, then setting this class as the class of the UIWindow object in your main XIB file. sendEvent: will be called each time the user generates a touch event. Unfortunately, at this point you cannot yet know which UI object will finally consume the event (read: which event handler code will be ultimately called) since that depends on the actual state of the responder chain. But anyway, you can use this method to inject events into the system.