update 2
viewDidAppear is executed twice, once before and once after, the overlay button is touched. Would a fix be to add a conditional to viewDidAppear which would return control to the calling class? If so, I would appreciated suggestions. Or maybe the very fact that viewDidAppear execute twice suggests another approach to a fix?
update 2
update 1
Maybe the problem is my usage of viewDidAppear and viewDidLoad shown below. Can anyone help, please?
- (void)viewDidAppear:(BOOL)animated
{
self.overlayViewController = [[BSsetupOverlayViewController alloc] initWithNibName:#"BSsetupOverlayViewController" bundle:nil] ;
// as a delegate we will be notified when pictures are taken and when to dismiss the image picker
self.overlayViewController.delegate = self;
[self showImagePicker:UIImagePickerControllerSourceTypeCamera];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
update 1
update 0
Perhaps I was not clear that the difference between the version that does not work and the one that does is that Storyboard is used in the one that does not work. Why would a done button work without Storyboard, but not with, even though only a nib is involved with the overlay?
update 0
The UIButton here was able to dismiss the camera preview, but in my actual app, tapping the UIButton only temporarily dismisses the preview and overlay screen. Immediately the preview returns. I think the problem is with the way I am implementing the delegate to the UIImagePicker, but I may be wrong.
I have created setup.zip here which contains a sample project with the undesirable behavior.
I took this question to the North Atlanta iOS Meetup and suggested that a conditional clause might fix the problem, as I mentioned in update 2 of the question. The founder of the Meetup, Kurt Niemi, quickly showed how to do so by editing the BSsetupViewController class.
First he added a Boolean property to the interface.
#property (nonatomic, assign) BOOL alreadyDisplayed;
Second he added a clause to the viewDidAppear method.
if (self.alreadyDisplayed)
{
self.alreadyDisplayed = FALSE;
[self dismissViewControllerAnimated:NO completion:nil];
return;
}
self.alreadyDisplayed = TRUE;
And last he added a slight unnecessary clause to the viewDidLoad method.
self.alreadyDisplayed = FALSE;
I still wish these steps were unnecessary, but they seem to work.
Related
I've an app which consists of a UITabBar with three views one of which is a UITableVIew. The first view that loads when the app boots is a UIView held within the UITabBar view. This view is a form for the user to fill in which takes them through five different screens. Previously I've been loading these as modal views one on top of the other and at the end dismissing them all when the user hits the final button like so:
[self.parentViewController.parentViewController.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
However since [self.parentViewController dismissModalViewControllerAnimated:YES] no longer works and has been replaced with [self dismissViewControllerAnimated:YES completion:nil]; I'm not really sure how to achieve this multiple dismissal of view controllers. I've tried adding the calls to parent view controller but that doesn't work. I've also tried:
[self.presentingViewController.presentingViewController.presentingViewController.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
But that doesn't seem to work either. Any advice would be much appreciated. I'm also getting the message in the console: Application windows are expected to have a root view controller at the end of application launch. Is this what's causing the problem?
Please note, this is the first time in ages I've been programming for iOS, I've been devoting most of my time recently to Arduino and interfacting electornics with coding so this is a bit of a steep refresher course I'm on.
Help would be much appreciated.
If your five view controllers are pushed onto a UINavigationController, then they can all be dismissed/popped with one command:
- (NSArray *) popToViewController: (UIViewController *) viewController
animated: (BOOL) animated
[It doesn't appear that you are using a UINavigationController... but it wasn't entirely clear from your description.]
I am having a really weird issue when testing on my 1st gen. iPad (running iOS 5).
I have a UIView that I use as a property (with retain). I nil the property in the parent view's dealloc method. Pretty basic stuff. It works perfect on my iPad 3 running iOS 6, but doesn't get released on my 1st gen.
Any ideas what might be going on?
I'm not using ARC.
If you're retaining it, you have to release it. You can't just nil the instance variable.
So if you're property looks like this:
#property (nonatomic, retain) UIView *myView;
You're dealloc would either look like this:
- (void)dealloc
{
[myView release], myView = nil;
[super dealloc];
}
Or this:
- (void)dealloc
{
[self setMyView:nil];
[super dealloc];
}
Or this:
- (void)dealloc
{
self.myView = nil;
[super dealloc];
}
And your property will properly get released--unless something else is retaining it.
So I figured this out. It seems to be a bug in the iOS 6 SDK or maybe I just don't understand it. I have a UIViewController that presents another vc via presentViewController:animated:completion: —If I dismiss the presented vc then it releases and subsequently all subviews are removed and all is well.
However, if while the presented vc is showing, I remove/destroy the parent vc, the presented vc is deallocated but, its subviews are not told to removeFromSuperview; This doesn't show up as a leak in instruments, BUT it does prevent the subviews from deallocating.
This does not happen on iOS 6, thus I suspect this is a bug in iOS 5. Everything releases/deallocates as one would expect on iOS 6.
If someone has an explanation, or a better understanding of this, I would love to reward the answer to them instead of myself.
A view controller isn't responsible for removing its view from the superview when the view controller is dealloc'ed. The view controller is just responsible for releasing its own reference to it.
For example: you can create a view controller, ask for its view, then add that view to another view and throw away the view controller. In that case, you're just using the view controller as a view builder.
I'm not sure why the behavior is different in iOS 6, but would love to know.
I am adding a dummy ScrollView to my app to detect a user click on the status bar, to performa an event in my program.. I am creating it in the ViewDidLoad:
//Dummy Scroll is for the tap on status bar to work
UIScrollView *dummyScrollView = [[UIScrollView alloc] init];
dummyScrollView.delegate = self;
[[self view ] addSubview:dummyScrollView];
[[self view] sendSubviewToBack:dummyScrollView];
I then implement :
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
NSLog(#"scrollViewShouldScrollToTop");
.
.
}
Under all previous versions of IOS this has worked beautifully and flawlessly, yet under iOS 6 the scrollViewShouldScrollToTop never gets called. Is this a bug?? The API says this should still be available as part of the delegate in iOS6, yet under iOS6 on both device and simulator it never executes... Anyone have any idea what is going on?
Still no other TableView or ScrollView, but there is a MAPVIEW?? But the MapView doesn't have a shouldScrollToTop that I can find to set to NO.. so I am still beyond confused why this stopped working under iOS 6...
Is there any chance that the UIScrollView you're creating isn't somehow the only UIScrollView in your view hierarchy? It looks like in iOS6, if you have more than a single UIScrollView in your view hierarchy, only one should have scrollsToTop = YES. This is the one that'll have its scrollViewShouldScrollToTop method called.
My problem was similar in that I had a very basic UITableView that would no longer autoscroll to the top when the status bar was tapped. I finally remembered that one of the cells in my tableView uses a UIWebView, and that the cell's webView.scrollView was (correctly, now in iOS6) hijacking the call to scrollViewShouldScrollToTop that, before iOS6, was being made on my tableView.
After setting the tableViewCell's "scrollsToTop = NO", the status bar autoscroll once again worked as it did before. Here's more-or-less how the code looks:
myCustomCellWithAWebView.webView.scrollView.scrollsToTop = NO;
Hope this helps!
On iOS 6, only tap the part above scrollview of status bar can fire scrollsToTop event.
And, that scrollView can't be hidden or 0 alpha.
But it can be covered. or clear background color.
So on iOS 6, you need
dummyScrollView.frame = self.view.bounds;
dummyScrollView.backgroundColor = [UIColor clearColor];
I'm very new with iOS Development and I have just created one of my first apps, in my .xib file I have a UINavigationBar that I want to hide/show when a part of the screen is tapped by the user (like in the Photo app). I've found some snippets online but I don't know where and how to use those.
I'd appreciate a lot if somebody could give me detailed informations about how to do this.
Add this toggle method anywhere in your UIViewController. This hides on first tap and shows again in second tap.
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navigationController.navigationBar.hidden;
[self.navigationController setNavigationBarHidden:!barsHidden animated:YES];
}
If there is no navigation controller, link the navigation bar with an IBOutlet and replace with
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navBar.hidden;
self.navBar.hidden = !barsHidden;
}
Then add the following in the method -(void)viewDidLoad {}
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(toggleNavBar:)];
[self.view addGestureRecognizer:gesture];
[gesture release];
If the view where you are going to tap is a UIWebViewController, you have to add the protocol to the view controller and set it as delegate gesture.delegate = self; then add the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
This is needed because the UIWebViewController already implements its own gesture recognizers.
Ultimately, you want to send the -setHidden: message to your navigation bar. The easiest way to do this is to make an Outlet and an Action in your in your view controller. Then, in your .xib file, connect the navigation bar to the outlet and some button (even a large, full screen one) to the action.
Outlets and Actions are basic techniques used over and over in iOS
(and Mac) programming, so if you don't understand them, best go read
up on them now. Every beginning iOS/Mac programming book covers this
topic as does Apple's own Getting Started guide (pay particular
attention to the Configuring the View section).
Inside your action, send a message to the outlet like so:
-(void)myButtonAction:(id)sender{
[[self myNavigationBarOutlet] setHidden:YES];
}
This will hide the navigation bar whenever your button is tapped.
(This assumes you have a UINavigationBar in your .xib like you say. These directions will be different if you're working with a UINavigationController that manages its own UINavigationBar)
i am currently trying to do a bar graph in XCode. I have tried CPGraph and all the stuff around but they are all out of date and i need help for XCode 4. I am completely newb with this and that's why i need your help.
Here is my code:
-(void)drawRect:(CGRect)rect
{
NSString *s = textField.text;
value = [s intValue];
NSLog(#"%i",value);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 60);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, 400, value);
CGContextAddLineToPoint(context, 400, 100);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}
Notice that i have changed one of the point value for "value".
What i have done is create a UITextField and i want to be able to write like 500 in the UITextField and that the bar adjust itself. Currently the NSLog tell me that value is equal to 0 even if, before building my app i manually enter a number in the TextField.
I have been searching fo 3 days now and everything i found give me errors and are incomplete as i says i know almost nothing about objective-c in xcode. I also noticed during my search that this type of line doesn't refresh real time if you dont tell him. I would like help with that too if that's part of my problem. If you want more information on my code just tell me.
I will be really grateful if somebody can help me.
here is my .h :
#interface draw2D : UIView
{
UITextField *textField;
}
#property (nonatomic, retain) IBOutlet UITextField *textField;
#end
OK, it looks like since you have your text field hooked up in IB to File's Owner, that is typically your app delegate which is not the class you have above as that is a UIView. So, not unless you changed File's Owner to this UIView then your text field is not hooked up. So, typically what I do is to add a UIView to the xib window in IB (if you are not using the one that comes free when you create a XIB). Then that is what I'll attach the text box to, not File's Owner. Kind of begs the question of how anything is attached to Files Owner not unless you have a UITextField declared in there too (again providing you didn't change the class from the app delegate to this view class).
I know that if someone is new to this is is almost like greek. I developed in Java, C/C++, C#, etc for years and this was like learning how to program all over again.
If you are new to this I highly suggest the iPhone dev book by Big Nerd Ranch. I found it very useful.
OK, I found out how to redraw my line with a button refresh.
What I did was create a button and link it with my UIView where my line is being drawn. Inside I wrote [self setNeedsDisplay]; and each time I click the button it refreshes the view and gives me back my NSlog that I set in the same method as my drawRect.
Many thanks again Merky.