viewDidLoad getting called before initWithFrame? - iphone

I have a custom init method:
- (id) initWithFrame:(CGRect ) frame andImage:(UIImage *) image
{
self = [super init];
if (self){
self.view.frame = frame;
self.imageView_.image = image;
self.imageScrollView_.frame = self.view.frame;
imageOriginalFrame = frame;
zoomedImageFrame = frame;
NSLog(#"SCREEN DIM %f AND %f", zoomedImageFrame.size.height, zoomedImageFrame.origin.y);
}
return self;
}
and here's how I present it:
FullSizeImageViewController * fullSize = [[FullSizeImageViewController alloc] initWithFrame:imageOriginalFrame andImage:image];
if ([self.delegate respondsToSelector:#selector(fullStoryViewController:presentModalViewController:animated:)]) {
[self.delegate fullStoryViewController:self presentModalViewController:fullSize animated:YES];
}
However, surprisingly my viewDidLoad is getting called before the initWithFrame. How is this possible?
I am guessing it's because I call super init? If not how do I do this?

Your viewDidLoad method is not getting called before your initWithFrame:andImage: method. Your viewDidLoad method is getting called during your initWithFrame:andImage: method.
Your initWithFrame:andImage: method contains this line:
self.view.frame = frame;
which is shorthand for this:
[[self view] setFrame:frame];
So your method is calling the -[UIViewController view] method. The -[UIViewController view] method is basically this:
- (UIView *)view {
if (!_view) {
[self loadView];
[self viewDidLoad];
}
return _view;
}
Try putting a breakpoint in your viewDidLoad method. When it's hit, look at the stack trace. You'll find initWithFrame:andImage: in it.

Related

Dissmissing the keyboard when UITextField and UITextview displayed inside of UIWindow

I've added my UITextField and UITextView inside a UIWindow I can not able to type inside in both of them. Both are not letting me allow to type in those fields. And, can't able to dismiss it when return pressed in keyboard.
-(void)showAlert
{
alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
alertView = [[UIView alloc] initWithFrame:CGRectMake(10, 115, 300, 230)];
alertWindow.windowLevel = UIWindowLevelAlert; // puts it above the status bar
alertView.center = CGPointMake(alertWindow.frame.size.width/2, alertWindow.frame.size.height/2);
alertView.backgroundColor = [UIColor whiteColor];
alertView.layer.borderWidth = 1.0;
alertView.layer.borderColor = [[UIColor whiteColor]CGColor];
UITextField *txt = ....
....
....
txt.delegate = self;
...
...
[alertView addSubview:txt];
UITextView *txtview = ...
....
....
txtview.delegate = self;
...
[alertView addSubview:txtview];
[alertWindow addSubview:alertView];
[alertWindow addSubviewWithZoomInAnimation:alertView duration:1.0 option:curveValues[0]];
[alertWindow setHidden:NO];
}
I've declared both of the delegate methods also. I placed a breakpoint there and checked also, even that method not yet called.
Update -
textFieldShouldReturn delegate method
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
[reserveView resignFirstResponder];
[reserveWindow resignFirstResponder];
[self.reserveWindow endEditing:YES];
[reserveView endEditing:YES];
return YES;
}
You should try this for dismiss the keyboard from the UIWindow
[self.window endEditing:YES];
Source
I found, that method has not been called because of UIWindow So, i changed my UIWindow to UIView And, i fixed this issue by using UIView+Animation.h from here It provides the animation what i required exactly.
- (void) addSubviewWithZoomInAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option;
- (void) removeWithZoomOutAnimation:(float)secs option:(UIViewAnimationOptions)option;
Thanks to Google! Cheers!
The keyboard will never dismiss on its own (even if you hit return!). You'll notice that in your delegate methods, you will receive events whenever you press return/done/etc.
A simple way to make the keyboard dismiss every time someone hits the return key is to implement the - (BOOL)textViewShouldEndEditing:(UITextView *)textView method.
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
[textView endEditing:YES];
return YES;
}
Edit: In your post you edited to say that you've declared both of the delegate methods... there are more than two so could you clarify what methods you've implemented? http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextViewDelegate_Protocol/Reference/UITextViewDelegate.html#//apple_ref/occ/intf/UITextViewDelegate
Try this
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
tapGesture.cancelsTouchesInView = NO;
[self.window addGestureRecognizer:tapGesture];
//[self.view addGestureRecognizer:tapGesture];
[tapGesture release];
}
-(void)dismissKeyboard
{
[txt resignFirstResponder];
[textView resignFirstResponder];
}
Try this
That's the delegate method of textfield:-
(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[txtview resignFirstResponder];
return NO;
}

Crash when trying to setup gesture recognition

I'm trying to setup a tap gesture in my code and I get a crash when I try to determine the coordinates. Any help would be appreciated.
2012-09-14 17:25:49.149 valhalla[16469:707] tap detected
2012-09-14 17:25:49.159 valhalla[16469:707] -[UITapGestureRecognizer translationInView:]: unrecognized selector sent to instance 0x37bf10
2012-09-14 17:25:49.165 valhalla[16469:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITapGestureRecognizer translationInView:]: unrecognized selector sent to instance 0x37bf10'
*** First throw call stack:
(0x3104c88f 0x3611d259 0x3104fa9b 0x3104e915 0x3104f788 0x7a4a1 0x31870637 0x31800d65 0x31a31479 0x3177cf55 0x3177baa3 0x317887e9 0x31788627 0x317881f5 0x3176e695 0x3176df3b 0x313e222b 0x31020523 0x310204c5 0x3101f313 0x30fa24a5 0x30fa236d 0x313e1439 0x3179ccd5 0x75307 0x752c8)
#import "GLViewController.h"
#import "GLView.h"
#implementation GLViewController
- (void)loadView {
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
GLView *glView = [[[GLView alloc] initWithFrame:applicationFrame] autorelease];
self.view = glView;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleTap:)];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];
[singleTap release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// We can run in landscape mode
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
/*- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//[self.view becomeFirstResponder];
//[self.view setReturnKeyType:UIReturnKeyDone];
}*/
- (void)didReceiveMemoryWarning
{
// default behavior is to release the view if it doesn't have a superview.
// remember to clean up anything outside of this view's scope, such as
// data cached in the class instance and other global data.
[super didReceiveMemoryWarning];
}
- (void) handleSingleTap: (UIPanGestureRecognizer *) uigr
{
NSLog(#"tap detected");
CGPoint translation = [uigr translationInView:self.view];
CGPoint finalPosition = self.view.center;
finalPosition.x += translation.x;
finalPosition.y += translation.y;
}
#end
Your declaring a UITapGestureRecognizer but your method is casting to a UIPanGestureRecognizer
- (void) handleSingleTap: (UIPanGestureRecognizer *) uigr
UITapGestureRecognizer does not declare translationInView. That is why your app is crashing.
You want to be using locationInView: not translationInView:

I currently have a accelerometer action that displays a image but won't clear/reset

For a exercise I created a project to experiment with the accelerometer functions of the iPhone. Right now when I run the app on my device it begins with a blank screen, shake the phone and a image is displayed.
I have to force close the app to clear the image. I was hoping someone could provide a solution that would make the image reset so I could repeat the process as many times as I wanted. (shake phone, display image, clear image) I'm thinking it needs a timer or something, not sure. Here is the source code. Thanks for taking the time to read and help.
// ViewController.m
// AccelTest
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
-(void)viewWillAppear:(BOOL)animated{
[self startAccel];
[self view];
}
-(void)viewWillDisappear:(BOOL)animated{
[self stopAccel];
[self view];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
double const kThreshold = 2.0;
// double const kThreshold = 2.0;
if ( fabsf(acceleration.x) > kThreshold
|| fabsf(acceleration.y) > kThreshold
|| fabsf(acceleration.z) > kThreshold){
[self.view addSubview:[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Icon.png"]]];
}
}
-(void)startAccel{
UIAccelerometer * accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = .25;
}
-(void)stopAccel{
UIAccelerometer * accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = nil;
}
#end
Here is how I would do it (without ARC) to tap the image to make it disappear.
Remove your line:
[self.view addSubview:[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Icon.png"]]];
And add these lines instead:
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Icon.png"]];
myImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(rm:)];
[myImageView addGestureRecognizer:tapgr];
[tapgr release]; tapgr = nil;
[self.view addSubview:myImageView];
[myImageView release]; myImageView = nil;
Then add a method to the View Controller to remove the UIImageView when it is tapped.
-(void)rm:(UITapGestureRecognizer *)tapgr {
[tapgr.view removeFromSuperview];
}
When that Image is tapped once, the rm: method will be called which will remove the Image from self.view
Store a pointer to that image view somewhere and remove it from it's superview when you want to. Either with a timer, or user action, or something like that.

UITableView scrolls too far when editing embedded UITextView

I've successfully embedded a UITextView inside a UITableViewCell, and most of the table is working fine. However, when I enable editing on the UITextView and start editing, the table shifts up too far, obscuring the cursor. Is there a way to control how far the tableview scrolls? Manually scrolling the view to the cell works, but the view still scrolls up before scrolling back down and into view.
Here is an example of what I mean:
editing a UITextField - the field is neatly placed directly above the keyboard.
http://imageshack.us/photo/my-images/13/textfield.png/
editing a UITextView - the field is placed significantly above the keyboard removing the toolbar from the keyboard doesn't affect anything)
http://imageshack.us/photo/my-images/809/textview.png/
Here's all the code that is relevant to the UITextView in the UITableViewController object:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillShow:)
name: UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillHide:)
name: UIKeyboardWillHideNotification object:nil];
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
viewTargetedForEditing = (UIView *)textView;
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[self.navigationController setNavigationBarHidden:YES animated:YES];
// shrink the textView to fit on-screen
originalTextViewFrame = textView.frame;
CGRect keyboardRect = [[keyboardUserinfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardRect.size.height;
CGRect newViewFrame = textView.frame;
CGFloat spaceAboveKeyboard = self.containerView.frame.size.height - keyboardHeight;
newViewFrame.size.height = (spaceAboveKeyboard < textView.frame.size.height) ? spaceAboveKeyboard : textView.frame.size.height;
/* animate the calculations */
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[keyboardUserinfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
textView.frame = newViewFrame;
[UIView commitAnimations];
// recalculate the keyboard height, in case we aren't in portrait mode
CGFloat toolbarHeight;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
toolbarHeight = 44.0;
} else {
toolbarHeight = 32.0;
}
CGRect frame = textView.inputAccessoryView.frame;
frame.size.height = toolbarHeight;
}
- (void)endTextViewEditing
{
[viewTargetedForEditing resignFirstResponder];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
#pragma mark - Keyboard Notifications
- (void)keyboardWillShow:(NSNotification *)notification
{
[keyboardUserinfo release];
keyboardUserinfo = [[notification userInfo] retain];
[self viewDidBeginEditing:viewTargetedForEditing];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[keyboardUserinfo release];
keyboardUserinfo = [[notification userInfo] retain];
[self viewDidEndEditing:viewTargetedForEditing];
}
- (void)viewDidBeginEditing:(id)aView
{
// called 2nd
UITableViewCell *cell = (UITableViewCell *)[aView superview];
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)viewDidEndEditing:(id)aView
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[viewTargetedForEditing superview]];
gallupAppDelegate *appDelegate = (gallupAppDelegate *)[[UIApplication sharedApplication] delegate];
switch (indexPath.section) {
case SectionDescription:
if (![[(UITextField *)aView text] isEqualToString:self.plan.Description]) {
self.plan.Description = [(UITextField *)aView text];
[appDelegate saveManagedContext];
}
break;
case SectionNotes:
if (![[(UITextView *)aView text] isEqualToString:self.plan.Notes]) {
self.plan.Notes = [(UITextView *)aView text];
[appDelegate saveManagedContext];
}
break;
case SectionLocation:
if (![[(UITextField *)aView text] isEqualToString:self.plan.Location]) {
self.plan.Location = [(UITextField *)aView text];
[appDelegate saveManagedContext];
}
break;
}
}
The TextViewCell is a subclass of UITableViewCell, and it is the cell that is giving me the problem with scrolling.Here's the implementation:
#implementation TextViewCell
#synthesize contents=_contents;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_contents = [[UITextView alloc] initWithFrame:CGRectZero];
[self addSubview:_contents];
self.contents.font = [UIFont systemFontOfSize:17];
self.contents.dataDetectorTypes = UIDataDetectorTypeAll;
CGRect frame = CGRectMake(0, 0, self.window.frame.size.width, 44.0);
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(endTextViewEditing)];
UIToolbar *textViewToolbar = [[UIToolbar alloc] initWithFrame:frame];
textViewToolbar.barStyle = UIBarStyleBlackOpaque;
[textViewToolbar setItems:[NSArray arrayWithObjects:spacer, done, nil]];
self.contents.inputAccessoryView = textViewToolbar;
}
return self;
}
- (void)endTextViewEditing
{
[self.contents resignFirstResponder];
}
#define LEFT_MARGIN 15
#define TOP_MARGIN 5
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat width = self.frame.size.width - (LEFT_MARGIN *2);
CGFloat height = self.frame.size.height - (TOP_MARGIN *2);
self.contents.frame = CGRectMake(LEFT_MARGIN, TOP_MARGIN, width, height);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
//[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc
{
[super dealloc];
}
#end
As it turns out, subclassing the UITableView and implementing the following fixed the problem:
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
[super setContentOffset:contentOffset animated:animated];
return;
static int i = 0;
if (0 == i) {
i++;
} else {
i = 0;
[super setContentOffset:contentOffset animated:animated];
}
return;
}
Apparently the -setContentOffset:animated: message was sent 2x, and if the first one is allowed to run the second time round doesn't do it's job properly.
Does anyone have any insite as to why this would fix the problem?

How do I unload a UIViewController from a UIScrollView?

I am using pretty much the same code to load my UIViewController (called LessonScrollView) into the UIScrollView. The method is called when in the scrollViewDidScroll method
- (void)loadScrollViewWithPage:(int)page {
if (page < 0)
return;
if (page >= numPages)
return;
LessonScrollView *controller = [imageViewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
controller = [[LessonScrollView alloc] initWithPage:page forLesson:[self title]];
[imageViewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
if (controller.view.superview == nil) {
CGRect frame = CGRectMake(0, 80, 320, 285);
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
In some circumstances I have quite a few pages, which I believe, remain in memory until the UIViewController responsible for the scrollView is released (or a memory warning occurs).
My question is, how would I release the LessonScrollView object. I would call a method called, say
- (void)unloadScrollViewWithPage:(int)page
in scrollViewDidScroll and page would be the current page - 1.
Thanks for any help you can offer.
Try this:
[controller.view removeFromSuperview];//to release the controller's view
[imageViewControllers replaceOjectAtIndex:page withObject:[NSNull null]];//to release the actual controller which should lead to it being dealocated