Odd problem with UIView touch handling - iphone

For my iPad app, I'm using a UIViewController subclass called SidebarViewController to display some stuff in a sidebar. In the sidebar I have a calendar control. I'm using the open source Kal component from http://github.com/klazuka/Kal. In the -viewDidLoad method of SidebarViewController, I'm creating a new instance of KalView (the main view for the calendar) and adding it as a subview of SidebarViewController's view:
_logic = [[KalLogic alloc] initForDate:[NSDate date]];
_calendarView = [[KalView alloc] initWithFrame:CGRectMake(0.0, 62.0, 273.0, 239.0) delegate:self logic:_logic];
KalDate *currentDate = [KalDate dateFromNSDate:[NSDate date]];
[_calendarView selectDate:currentDate];
[self.view insertSubview:_calendarView atIndex:0];
The calendar displays and everything, but there's one problem. The main component of the calendar is the KalGridView, which is a subview of KalView. It displays the date tiles, etc. When the app starts, for some reason, the KalGridView does not receive touches. The touches are intercepted by SidebarViewController's view. Weirdly enough, if I tap the month change buttons at the top of the calendar to change the month, the KalGridView starts receiving touches again.
I can't figure out why this is happening, because none of the other subviews of SidebarViewController are affected by the same issue.

Creating the KalView in the XIB instead of creating it in code seemed to solve the problem. This definitely looks like a bug, but I don't know the circumstances under which it can be reproduced so I don't think I can file it.

Related

Keyboard shows then immediately hides itself when showing MFMessageComposeViewController

I am building a PhoneGap app using Cordova 2.2 for IOS. I am experiencing some bizarre behavior when calling out to a native obj-c plugin I have written to show the MFMessageComposeViewController.
The setup is very simple - I have a tap event attached to a UI element, that when pressed, will make a call to my PhoneGap plugin, pass with it a number and a text message, then show the MFMessageComposeViewController with the parameters pre-populated.
My javascript looks like this:
$(document).bind('deviceready', function(){
$(".theButton").tap(function(){
cordova.exec(function(){}, function() {}, "PhoneGapSms", "SendSms", [db.getItem("profile_sms"), db.getItem("profile_emergency")]);
});
});
And my obj-c code looks like this:
- (void)SendSms:(CDVInvokedUrlCommand*)command
{
CDVInvokedUrlCommand* myCommand = command;
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
NSString* body = [command.arguments objectAtIndex:0];
NSString* toRecipientsString = [command.arguments objectAtIndex:1];
if(body != nil)
picker.body = body;
if(toRecipientsString != nil)
[picker setRecipients:[ toRecipientsString componentsSeparatedByString:#","]];
picker.messageComposeDelegate = self;
[self.viewController presentModalViewController:picker animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[picker release];
}
So, all in all, very simple stuff.
My Problem is this:
When my iPhone is plugged into my Mac and the app is run from XCode, the Message Composer overlay appears great, with my values pre-populated. Image below demonstrating the SMS interface appears fine while plugged into XCode:
When my iPhone is unplugged from my Mac, and the app is run from the spring board, the Overlay slides up, the keyboard begins to slide up, then immediately slides down - making it impossible to type or send the message. This is what it looks like when not attached to the Mac/Xcode - the keyboard begins to slide up then immediately slides down (~ < 1 sec) leaving the following interface:
I can't for the life of me figure out what would cause the keyboard to hide when not running from XCode, but work perfectly well when it is.
Is there any way to 'force' the keyboard to display, or possibly put the whole modalviewcontroller as first responder in some form or fashion?
Any suggestions are appreciated!
Edit:
The keyboard WILL appear again if you click in the contact area
You must add MessageUI.framework to your Xcode project and include a
#import <MessageUI/MessageUI.h> in your header file.
try this code may be its helpful to you..
[self presentModalViewController:picker animated:YES];
//[self becomeFirstResponder];//try picker also instead of self
Also Refer this bellow tutorial and also check demo..
new-tutorial-developing-and-architecting-a-phonegap-application
SMSComposer
i hope this help you...
I encountered these symptoms with a Sencha Touch 2.2 and Cordova 2.6.0 setup (specifically, iOS 6+ devices).
The issue was with the web framework stealing focus away from the native SMS Composer modal, typically occurring after the first SMS Composer modal had been successfully displayed and closed.
A event.preventDefault() and event.stopPropagation() call once the event had been fired (or event.stopEvent() in Sencha land) resolved this.
Hope this helps,
-James
First: The most likely culprit, without seeing your code, is that your parent (presenting) view controller may have an action in its viewWillDisappear or viewDidDisappear that is affecting who has the "first" responder. These methods get called when presenting a view controller modally. It may be behaving differently on the simulator than the device due to timing - often really close timing conditions are different on the ARM device and the i386 processor.
Second: Does anywhere in your app register for the UIKeyboardWillShowNotification or the UIKeyboardDidShowNotification? If so, put breakpoints in the methods that are called as a result - it's possible some other controller in your view hierarchy is interfering with this one.
To answer your question...
Is there any way to 'force' the keyboard to display, or possibly put the whole modalviewcontroller as first responder in some form or fashion?
No to both. The only way to make the keyboard display is to call the becomeFirstResponder method of the input view. Since Apple doesn't expose the text view, you cannot send it messages. Setting the modalViewController as first responder would be setting the wrong object.
I found the same type of issue But Not Sure it will Solve your problem or not Just Have a Look on the Following Links :
1. http://community.phonegap.com/nitobi/topics/keyboard_is_not_triggerd_in_my_ios_build
2. https://github.com/phonegap/build/issues/31
If its not Solving your issue then you can Download the Sample code Here.
Link: https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/SMSComposer

Problem when adding Three20 PhotoViewer to my UINavigationViewController

I want a photo viewer in my iphone app and I liked the Three20 photo viewer. I found it somehow hard to integrate it in my own app where I have my typical UINavigationViewController. So far I succeeded in doing the following:
TTURLMap *map = [[[TTURLMap alloc] init] autorelease];
[map from:#"tt://appPhotos" toSharedViewController:[PhotoViewController class]];
[self.navigationController pushViewController:[map objectForURL:#"tt://appPhotos"] animated:YES];
The only problem is that wenn I click back to my original view, its navigation bar keeps the style of the photo viewer (transperant and shows the view under it).
How can I get back my original navigation bar?
My experience: I once used three20's PhotoViewer and every time I went back from the PhotoViewer to my other view. The system status bar remained black and transparent (while it should be with default style). I solved it by manually and programmatically changing the status bar style every time when the back action was triggered.
Yes, this is a bit of an issue for sure. A good solution, as #diwup says, is to implement a manual fix. I tend to subclass TTPhotoViewer when I need it. Not only does it help with this problem but it also makes it much easier to use I find.
If you decide to subclass, then you should use whatever variation of the following you require:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationController.navigationBar.tintColor = myTintColor;
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}
However, if you don't want to subclass, you can always put the code into the - [viewWillAppear:] method of any class that comes after the photo viewer.

ABPersonViewController drawn under the navgation bar

The context:
I am working on an app that maintains a list of contacts along with their record IDs for it's own reference.
When the user needs to change the number associated with a specific contact within the app, I am trying to display the ABPersonViewController so the user can choose the new number from the contact in AB.
The problem:
The problem is that the ABPersonViewController that is opened is starting all the way from the top of the screen as if it does not know that there is a navigation bar on the top.
As a result some of the top part of the ABPersonViewController screen (the top part of the person image and the top part of the name) is underneath the navigation bar.
Ideally i want it to look like this, but not in edit mode: http://developer.apple.com/library/ios/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Art/person_view.jpg
Also I wanted to add a "cancel" button to the top right part of the nav bar. Trying to add that as a bar button is not working either.
The code:
this is how I am adding the ABPersonViewController to the navigationController:
ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
personViewController.personViewDelegate = self;
personViewController.displayedPerson = person;
[self.m_circleNavController pushViewController:personViewController animated:YES];
[personViewController release];
The self here is a UIVIewController.
The m_circleNavController is the UINavigationController to which the UIVIewController belongs.
I tried these 2 ways of showing the person view, but both behave the same way.
[self.m_circleNavController pushViewController:personViewController animated:YES];
[self.navigationController pushViewController:personViewController animated:YES];
I'm not too sure what I am doing wrong, or what is the best way to do it.
I tried a lot of different ways to display it in vain.
The viewcontroller was behaving as though it was starting about 40 pixels above the top edge of the screen.
I was able to fix it in a very weird way finally. In the init function of the viewcontroller I added the following line:
self.view.bounds = CGRectMake(0, -43, 320, 440);
But still no clue as to why it happens this way. I was to close to the deadline to look for a decent solution.
Hello I've been having the same problem as of the new iOS. When this happens on my custom view controllers I have been able to correct it with:
if (self.interfaceOrientation != UIInterfaceOrientationPortrait) { // UI is in landscape position
[self.tableView setContentInset:UIEdgeInsetsMake(32,0,0,0)];
} else { // UI is in portrait position
[self.tableView setContentInset:UIEdgeInsetsMake(44,0,0,0)];
}
But when using the ABPersonViewController I don't quite know how to handle this problem.
Hope someone has an idea...

ViewController displaced vertically by 20px after modal is dismissed: iOS4 Only. Example code included

I hope someone can help... This issue has been discussed here and I have tried the solutions suggested but to no avail.
My problem is best illustrated using the example project which can be downloaded from this URL:
http://www.hitsalive.com/tmp/VCTest.zip
In the example project I have a main UIViewController with two buttons used to call two other UIViewControllers - one using presentModalViewController and the other using "addSubView" (using the AppDelegate). Individually both buttons and UIViewControllers work fine.
However, if I first call the modal viewcontroller, then dismiss it (using dismissModalViewControllerAnimated: YES) and then display the second (addSubView) UIViewController, then all elements and subviews in the second UIViewController (such as the button in the example) get displaced downwards vertically by 20 pixels. And the displacement happens with a momentary delay.
This issue does not happen with SDK 3.2 and below -- just iOS4.
Any help would be appreciated, especially with reference to the example project above.
add [aViewControllerTwo setWantsFullScreenLayout:YES]; to your - (void)flipToViewControllerTwo after ViewControllerTwo *aViewControllerTwo = [[ViewControllerTwo alloc] initWithNibName:#"ViewControllerTwo" bundle:[NSBundle mainBundle]];
In order to solve this you need to do the following with the view controller that appears shifted: add a frame, then set the position of this frame appropriately. Set this frame to the view of the ViewController.
shiftedViewController* ShiftedViewController = [[ShiftedViewController alloc] init ];
CGRect theFrame = [shiftedViewController.view frame];
theFrame.origin.y = 20;
theFrame.origin.x=0;
[shiftedViewController.view setFrame: theFrame];
[self presentModalViewController:shiftedViewController
animated:YES];

iPhone OS: Tap status bar to scroll to top doesn't work after remove/add back

Using this method to hide the status bar:
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
When setting "hidden" back to NO, the tap-to-scroll-to-top (in UIWebView, UITableView, whatever) doesn't work any more, and requires a restart of the app to get the functionality back.
Is this a bug (I filed a rdar anyhow) or have I missed a step? Should I perhaps expect this behavior since the statusBar "loses touch" somehow with the respective view?
You could try setting the ScrollsToTop property to true again after re-showing it:
[currentView setScrollsToTop:YES];
If that's not working, are you definitely only showing one view? If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored...
In iOS 5.0 you can access the scrollview property of the UIWebView
webView.scrollView.scrollsToTop = YES;
The following fix by Alex worked for me. Thanks!
((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;
Being in a hurry this fix worked great, however given more time I might've subclassed the UIWebView and accessed the protected UIScrollView member directly.
The worry I have with Alex' method is that it assumes that UIScrollView is at index zero of the subviews (encapsulation allows private members to change). Which suggests another solution still:
for (UIView* v in [webView subviews])
{
if ([v isKindOfClass:[UIScrollView class]])
{
(UIScrollView *)v.scrollsToTop = NO;
}
}
I was having a similar problem where the scroll-to-top functionality was lost. Turns out this will only work when you have only one active view at a time (within the same scroll view). In my case I had a table view and another view which would fade in/out. Adding a removeFromSuperview at the end of the animation did the trick.
The answer was in the UIScrollView.h file comments:
/*
this is for the scroll to top gesture. by default, a single scroll visible scroll view with this flag set will get the call. if there is more than one visible with this
flag set or the delegeat method returns NO, the view isn't scrolled
*/
#property(nonatomic) BOOL scrollsToTop; // default is YES. if set, special gesture will scroll to top of view after consulting delegate
You can use the following code to have the UIWebView ignore scrollToTop without the extra UIScrollView:
((UIScrollView *)[[webView valueForKey:#"_internal"] valueForKey:#"scroller"]).scrollsToTop = NO;
I had a similar problem after playing a Youtube video within my app. scrollsToTop was still set to YES but tapping the status bar had no effect.
I finally realised that my app window was no longer the key window. After adding the following line to a UIWindow subclass (which I already had for other reasons) everything worked as it should again:
if (![self isKeyWindow]) [self makeKeyWindow];
I just ran across a similar behavior in the app I'm currently working on. In its case, if you load a YouTube video from within a UIWebView, scroll to top stops working for the rest of the application's life cycle. I kind of assume this might happen after loading the movie player as well, but haven't confirmed. That functionality has been around a lot longer and probably has fewer bugs.
When there are multiple scrollview, you can also set scrollUpToTop to NO for the others scrollview. cf:
setScrollsToTop with multiple UIScrollView classes and/or subclasses(UITableView)
I want to add my case, I add an UIWebView on an UIScrollView, as h4xxr had answered on the top:
If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored
So, I get a simply way to make it work on webView: just set the scrollView·s scrollsToTop property false.
And when tap the status bar, it won`t got intercepted by the scrollView, and the webView scrolls to the top!
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
scrollView.scrollsToTop = false; //igore scrollView`s scrollsToTop
[self.view addSubview:scrollView];
UIWebView *webView = [[UIWebView alloc] init];
webView.frame = scrollView.bounds;
[scrollView addSubview:webView];