In my iOS application, when the user pushes a button in a view, a NSTimer is trigered in the controller.
On the third tick, I would like to make the background of the view bliking.
I've written the blinking function in the view (it should't be written in the controller, should it ?)
I can trigger this blinking function in the controller by
LostView *lostView = (LostView* ) self.view;
[lostView blinkBackground];
But it's bad, isn't it ? The controller shoudn't know the view neither the name of the function ?
I would like to apply the MVC pattern
Is the observer/obervable pattern applicable in this situation ?
Thanks
No it's not bad at all. It looks like you implemented the method to make the view blink in the view itself. That's fine, because it's directly related to the visual representation (i.e. the view part of MVC). You could reuse that view in any other app that requires a blinking view.
Since that blinking is triggered by an NSTimer I assume that it's somehow dependent on the logic in this specific app. The view can't (shouldn't) know when it's supposed to blink (that would only be the case if that blinking was a direct reaction of an interaction with it or another related part of the UI - or it was part of a more complex element, for example a countdown timer that always starts to blink when it reaches the last 10 secs or so. For example the UIButton provides the possibility to highlight it self if it's touched.)
But if that blinking is a reaction of some state transition in your app, maybe some new data becomes available or a countdown is about to expire, the controller is a perfectly reasonable place to trigger that.
Related
I want to build some analytics into my app and I would like to send some data when user leaves current screen, though there are multiple ways he can do so (back button, other button, sidebar menu, etc). Is there any efficient way to do this? I really don't feel like implementing it to every possible button that can lead the user to different screen.
You should call your function inside viewWillDisappear, which is called every time the current view controller is about to disappear from screen. See the documentation of viewWillDisappear
Also see the view controller life cycle (thanks #Paolo for the tip) below (documentation).
So I have a basic game I'm developing for iOS.
There's a 2 player mode and it involves hitting buttons. Once the button is hit (or pressed) something happens in the game.
So, each player has half of the screen, with their own buttons inside of their half, that act independently.
Do I need to worry about if player 1 hits a button on the lower part of the screen at the exact moment player 2 hit's a button on the top part of the screen?
If I do, do I need to handle it like the answer in THIS QUESTION.
I figure the chances are extremely slim, but never-the-less should be handled.
You don't need to worry about them being tapped at the same time. Since your buttons are independent each one should have it's own action method that is called when tapped, and it's okay if those methods are called at the same time since they do their own thing.
The reason the question you linked to is different is that they wanted to do special logic IF both buttons were tapped. Since you don't care whether they were tapped at the same time, you don't need to implement that code.
I want a button that will become available at, say, 8 AM. I know how to check if the button is available when the view is loaded, but, if the user is looking at the button as the clock turns to 8 AM, how do I get the button to become active without loading the view?
The button should always be present. Use its hidden to hide and show it as necessary. Or you can use its enabled to enable or disable it as necessary, but this can require more work, because a disabled button might not automatically look disabled so the user won't understand that it isn't truly "available".
Thus we have three cases to deal with:
The user moves to this view controller, the view controller loads its view, and your code decides about the button state / visibility now. You've already handled this one.
The view controller is already present and the view is visible, and the availability-change moment comes. In this case you will need previously to have set up a notification to prompt the view controller to take action now. Do not loop perpetually watching the time. Use an NSTimer or similar (a local notification is also worth considering).
The view controller is covered by another view controller and then uncovered. Perhaps the state needs to have changed in the meantime. So you will also want to do this check generally in viewWillAppear:, not just in viewDidLoad.
When I demo my touch apps to remote teams the people on the other end dont know where I am touching. To remedy this, I have been working on an event intercepting view/window that can display touches over applications. No matter how may variations on nextResponder I call, I am unable to react to the touch and pass it along to the controllers underneath. Specifically scroll views dont react nor do buttons.
Is there a way to take an event, get its position, then pass it along to what ever component would have been responding to it initially (the controller underneath)?
Update:
I am making some progress with a UIView. The new view is always returning NO to pointInside.This works great for when the touch starts, but it doesnt track moves or releases. Is there a strategy to adding gesture recognizers to the touch in order to track its event lifecycle?
Joe
You could try creating your own subclass of UIApplication that overrides sendEvent:. Your implementation should call [super sendEvent:event] as well as process the event as needed.
Update your main.m and pass the name of you custom UIApplication class as the 3rd parameter to the call of UIApplicationMain.
After some more due diligence, I found my oversight. In the layer that was on top and displaying the touches, user interaction needed to be set to false. Once I set that to false, I was able to use that layer for display while catching events on the layers below. The project still isn't done but I am one step closer.
Take care,
Joe
I have always been a bit unclear on the type of tasks that should be assigned to viewDidLoad vs. viewWillAppear: in a UIViewController subclass.
e.g. I am doing an app where I have a UIViewController subclass hitting a server, getting data, feeding it to a view and then displaying that view. What are the pros and cons of doing this in viewDidLoad vs. viewWillAppear?
viewDidLoad is things you have to do once. viewWillAppear gets called every time the view appears. You should do things that you only have to do once in viewDidLoad - like setting your UILabel texts. However, you may want to modify a specific part of the view every time the user gets to view it, e.g. the iPod application scrolls the lyrics back to the top every time you go to the "Now Playing" view.
However, when you are loading things from a server, you also have to think about latency. If you pack all of your network communication into viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of your app. It may be good idea to first show the user an unpopulated view with an activity indicator of some sort. When you are done with your networking, which may take a second or two (or may even fail - who knows?), you can populate the view with your data. Good examples on how this could be done can be seen in various twitter clients. For example, when you view the author detail page in Twitterrific, the view only says "Loading..." until the network queries have completed.
It's important to note that using viewDidLoad for positioning is a bit risky and should be avoided since the bounds are not set. this may cause unexpected results (I had a variety of issues...)
This post describes quite well the different methods and what happens in each of them.
currently for one-time init and positioning I'm thinking of using viewDidAppear with a flag, if anyone has any other recommendation please let me know.
Initially used only ViewDidLoad with tableView. On testing with loss of Wifi, by setting device to airplane mode, realized that the table did not refresh with return of Wifi. In fact, there appears to be no way to refresh tableView on the device even by hitting the home button with background mode set to YES in -Info.plist.
My solution:
-(void) viewWillAppear: (BOOL) animated { [self.tableView reloadData];}
Depends, Do you need the data to be loaded each time you open the view? or only once?
Red : They don't require to change every time. Once they are loaded they stay as how they were.
Purple: They need to change over time or after you load each time. You don't want to see the same 3 suggested users to follow, it needs to be reloaded every time you come back to the screen. Their photos may get updated... you don't want to see a photo from 5 years ago...
viewDidLoad: Whatever processing you have that needs to be done once.
viewWilLAppear: Whatever processing that needs to change every time the page is loaded.
Labels, icons, button titles or most dataInputedByDeveloper usually don't change.
Names, photos, links, button status, lists (input Arrays for your tableViews or collectionView) or most dataInputedByUser usually do change.