Strange behaviour in viewWillAppear - iphone

I have a TabBar Controller with some tab bar item in it.
The first time that a user tap on a tab bar item, I want that a alertview is opened, so that the user can read some little instruction tips.
I have a global variable (say CONFIG), that hold some boolean valeus (CONFIG.tip1AlreadySeen, CONFIG.tip1AllreadySeen, etc.). All these boolean values are initializated to NO.
When the user tap a tab bar item, the viewWillAppear method in its viewcontroller is executed. In this method I put a code like this one:
-(void) viewVillAppear: (BOOL) animated {
extern CONFIG; // <- it's not the actual code but it indicates that a global variable must be used
[super viewWillAppear: animated];
if(CONFIG.tip1AlreadySeen == NO) {
CONFIG.tip1AlreadySeen = YES;
// code for showing the alertview
}
}
The strange thing is that this piece of code works perfectly in one viewcontroller but doesn't work in one another.
With some debug, I fidd out that in the another viewcontroller the code is executed but the assigment CONFIG.tipAlreadySeen = YES doesn't modify the actual value of CONFIG.tipAlreadySeen. This value is still NO. Unbelievable!!!
A little workaround was using the viewDidAppear method for changing the value:
-(void) viewVillAppear: (BOOL) animated {
extern CONFIG; // <- it's not the actual code but it indicates that a global variable must be used
[super viewWillAppear: animated];
if(CONFIG.tip1AlreadySeen == NO) {
// code for showing the alertview
}
}
-(void) viewDidAppear: (BOOL) animated {
extern CONFIG;
CONFIG.tip1AlreadySeen = YES;
}
...But I really did not understand what happened!!! Someone of you could explain this behaviour?
Thanks in advance!
Marco

Why must this be global and not contained in the view controller itself? Just a simple BOOL #property on your view controller that is toggled. And, to maintain this persistent across multiple runs of your application, save out the result to NSUserDefaults, which you in turn check each time you init your view controller.

Related

presentModalViewController is not working?

I am making an application using two view controlers. When I am working on my first view I have posibility to go to another view using button "Settings" and method conected to this button looks like this:
-(IBAction)Settings:(id)sender{
[self presentModalViewController:settingsHandle animated:YES];
settingsHandle is an object of a second view class which is alloceted when the first view is loaded.
My problem starts while I am in a second view and i call method which include NSTimer object. This method is working during hmmm lets say 30 sec but it also can be 5 min, the result of this method is calling onother view the 3rd one.
Everything goes fine while am waiting for the result of this function in a second view.The result is that i am in a 3rd view.
When, during the method is working I am going to the first view from the second (using [self dismissModalViewControllerAnimated:YES]; )I can see that the method has finished(using NSLOG) but [self presentModalViewController:thirdview animated:YES]; is not working, just nothing happens.
so to sum up:
Waiting for the result in a secodnview (Succes third view uploaded)
Waiting for the result in a firstview (fail nothing happens)
And my goal is to make it happens from the firstview!
You can't present a ModalViewController from a ViewController that is dismissed. So, you need to keep track of the visible ViewController and call presentModalViewController from there. In your scenario, the easiest solution would be to make your NSTimer invoke a method in your first ViewController which goes like this
- (void)presentViewController:(NSTimer *)timer
{
if(self.modalViewController == nil)
[self presentModalViewController:settingsHandle animated:YES];
else
[self.modalViewController presentViewController];
}
If you create the NSTimer in your 2. ViewController, you would of course need a reference to the first ViewController. You could just pass this reference like this
-(IBAction)Settings:(id)sender{
settingsHandle.myParentViewController = self; //You need to create this var in settingsHandle
[self presentModalViewController:settingsHandle animated:YES];
//...
}

Custom Detail Image View from Three20

I am pretty new with Three20. I have followed ray wenderlich's nice introduction to three20 and the examples within the three20 framework. When I click on a thumbnail in a thumbnail view (subclass of TTThumbsViewController) to launch a Details view, a standard Details image view (deployed by TTPhotoViewController or its super class). I would like to use my own implementation of a Details View instead of the default. I put the following code when I initiated the subclass of TTThumbsViewController and TTThumbsViewControllerDelegate method:
- (id)initWithDelegate:(id<TTThumbsViewControllerDelegate>)delegate {
[super initWithDelegate:delegate];
return self;
}
- (void)thumbsViewController: (TTThumbsViewController*)controller
didSelectPhoto: (id<TTPhoto>)photo {
[navigationController.pushViewController:photoDetailViewController
animated:Yes];
}
But the default TTPhotoViewController view still prevail. When I put a NSLog in the delegate method. I coud see the method was called. I think there is another delegate someone already set in TTThumViewController? Can someone recommend a way to display my detail photo view? Is there another thumbs view controller I can use? Any suggestion will be greatly appreciated.
I'm really new to all of this (coding, etc.) but I'll share what I've found. By looking up the definition of ttthumbsviewcontroller, I was able to find the following method(wrong term?):-
- (void)thumbsTableViewCell:(TTThumbsTableViewCell*)cell didSelectPhoto:(id<TTPhoto>)photo {
[_delegate thumbsViewController:self didSelectPhoto:photo];
BOOL shouldNavigate = YES;
if ([_delegate respondsToSelector:#selector(thumbsViewController:shouldNavigateToPhoto:)]) {
shouldNavigate = [_delegate thumbsViewController:self shouldNavigateToPhoto:photo];
}
if (shouldNavigate) {
NSString* URL = [self URLForPhoto:photo];
if (URL) {
TTOpenURLFromView(URL, self.view);
} else {
TTPhotoViewController* controller = [self createPhotoViewController];
controller.centerPhoto = photo;
[self.navigationController pushViewController:controller animated:YES];
}
}
}
In the else statement, I've found this calls the creation of the photoviewcontroller. By recalling this method (?) in the actual body of my own code and changing the body in the else statement I was able to add a custom detail view. Further down the definition of the ttthumbsnailviewcontroller, you can find that the creatPhotoViewController calls for an initiation of the PhotoViewController so calling that method(?) in the body of the code and initializing another view also works.
If someone can explain whether or not this is a good method of doing this (I have a feeling that is not), it would be appreciated. Also why does putting the method in the body of the code override the call there.

switch state in the FlipsideViewController?

in my app i have a switch in the flipsideview when i set it to on all work properly then i touch Done to return to the main view, now when i touch again the info button it appear off till now no problem but if i touch Done button (without touch the switch) it will called the function with off statement my question is how to check if the switch (on FlipsideView) is on let it on where i should write my code maybe i'll do it by myself but where to write the code
You could store the state as a member variable, then update the UI in viewWillAppear:animated:. For example, in FlipsideViewController.h file, declare a member variable called switchIsOn:
#interface FlipsideViewController : UIViewController {
BOOL switchIsOn;
// Other member variables here
}
#property (nonatomic) BOOL switchIsOn;
Then in FlipsideViewController.m:
#synthesize switchIsOn;
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.switch setOn:self.switchIsOn animated:NO];
}
You can set the value of self.switchIsOn in response to the switch being toggled. e.g. create a method like this:
-(IBAction)handleSwitch:(id)sender {
self.switchIsOn = self.switch.on;
}
and then bind that method to the switch's Value Changed event.
Hope this helps.

Reload the view in iphone (in viewWillAppear)

I got a little app that has a button whose click is handled via
- (IBAction)click:(id)sender { }
Now, what I want is after click() runs, I want the view to refresh/reload itself, so that viewWillAppear() is re-called automatically. Basically how the view originally appears.
Of course I can call viewWillAppear manually, but was wondering if I can get the framework to do it for me?
viewWillAppear is where to put code for when your view will appear, so it is more appropriate to put code that will be called repeatedly into another method like -resetView, which can then be called by both viewWillAppear and your click method. You can then call setNeedsDisplay from within resetView.
-(void)resetView
{
//reset your view components.
[self.view setNeedsDisplay];
}
-(void)viewWillAppear
{
[self resetView];
}
- (IBAction)click:(id)sender
{
[self resetView];
}

how do i add two delegates to a ui element at run time?

im trying to implement some behaviors when a mapview element scrolls... by coding a delegate for the scrollview inside of a mapview.
so, right now, i got a pointer to the scroll view used by the map view in my code.
however, i wish to set the delegate of this scroll view inside the map view, but the issue is that the mapview already sets up a default delegate for this scroll view inside the map view.
can i make my delegate implement all of the messages of the protocol, explicitly sending them to the mapview's default delegate while also implementing my own behaviors?
how else can i go about adding my own delegate behavior, to an already existing default delegate....?
thanks everyone,
michael
You could just get the existing delegate and save a reference for yourself:
origDelegate = [theView delegate];
And then set the object you want as the delegate:
[theView setDelegate:self];
Then when getting a delegate message, call the same method on origDelegate, modify the response if you want to (or if necessary), and then return the modified response:
- (BOOL)shouldViewDoSomething:(id)theView
{
BOOL result = [origDelegate shouldViewDoSomething:theView];
if (decision1)
{
result = !result;
}
return result;
}