Recipients field of MFMessageComposeViewController doesn't show in iOS 7 - ios7

The code below works fine in iOS 5/6. In iOS 7, it looks like this (red oval for emphasis).
Code:
if ([MFMessageComposeViewController canSendText]) {
self.messageComposer = [MFMessageComposeViewController new];
self.messageComposer.recipients = #[number];
self.messageComposer.messageComposeDelegate = self;
[self presentViewController:self.messageComposer
animated:YES
completion:nil];
}
Question: This is simple code. Is there some other external property, perhaps of the presenting view controller, that is affecting this? Anyone have a fix or workaround?
thanks.

I've found that the MFMessageComposeViewController's recipient field seems to take some of it's appearance from the UINavigationBar appearance proxy in iOS7. To work around this, I've done the following in my apps:
Create an empty custom UINavigationController subclass, which doesn't override any of UINavigationController's methods.
Use this custom UINavigationController subclass as a marker for any navigation controllers that I want to have custom appearance, by setting the custom class on the identity inspector in IB:
In my app delegate, set up the appearance of navigation bars like this:
[[UINavigationBar appearanceWhenContainedIn:[MyCustomNavigationController class], nil] ...];
This ensures that I get the navigation bar appearance I want in the controllers I want to customize, but preserves the standard navigation bar (and related) appearance in other controllers (like MFMessageComposeViewController). Here's a screenshot; note the standard appearance of MFMessageComposeViewController, with the custom navigation bar appearance on the popover in the background:

I faced same problem and here is my solution-
Before presenting your message composer( [self presentViewController:messageComposer animated:YES completion:nil]; )
set
[[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
and in delegate method
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
UIImage *backgroundImage = [UIImage imageNamed:#"Navigation Bar"];
[[UINavigationBar appearance] setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
[self dismissViewControllerAnimated:YES completion:nil];
}
Thats all!!

Related

Modal status bar and navigation bar text colors from UIActivityViewControllers in iOS 7

When I'm using a UIActivityViewController, after the user chooses an activity (such as Mail or Message), I can not change the text color for the status bar nor the text/tint color of the Cancel and Send navigation bar buttons. For the bar buttons, in the AppDelegate I've tried using:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
And nothing happens. However I am able to set the navigation bar title with this:
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], UITextAttributeTextColor, nil]];
I set the UIViewControllerBasedStatusBarAppearance to NO in the Info.plist. And put the line:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
in the AppDelegate, and have had no luck changing the status bar color at all. Any ideas?
As the UIActivityViewController presents the underlying model view controllers, we use this workaround to fix the status bar color issue:
#interface StatusBarColorApplyingActivityViewController : UIActivityViewController
#end
#implementation StatusBarColorApplyingActivityViewController
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
[super presentViewController:viewControllerToPresent animated:flag completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
if (completion) {
completion();
}
}];
}
#end
As you can see, this is just a class extending the UIActivityViewController overriding the presentViewController:animated:completion:. When the view controller has been presented we set the status bar style via UIApplication in the completion block. Then we call the original completion block given to the method, if any.
Rather than sub-classing from UIActivityViewController, we can change the tintColor of the navigation bar upon presenting it and revert it upon completion in the completionHandler. For example:
UIColor *normalColor = [[UINavigationBar appearance] tintColor];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// back to normal color
[[UINavigationBar appearance] setTintColor:normalColor];
}];
[self presentViewController:activityViewController animated:YES completion:^{
// change color to suit your need
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:25.0f/255.0f green:125.0f/255.0f blue:255.0f/255.0f alpha:1.0f]]; // ActionSheet options' Blue color
}];
In iOS 8 the UIActivityViewController presents its individual compose controllers on the root view controller of your application.
You need to subclass your root view controller (whether it be a UIViewController or UINavigationController) and add the following code.
#interface UINavigationControllerBarColor : UINavigationController
#end
#implementation UINavigationControllerBarColor
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
[super presentViewController:viewControllerToPresent animated:flag completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
if (completion) {
completion();
}
}];
}
#end
and then instead of initializing a UINavigationController in the AppDelegate or storyboard, initialize your newly subclassed controller.
Some other recommendations subclass the UIActivityViewController but this does not work.
If you want to change the bar button and title colors as well use the following in your application:didFinishLaunching:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor], UITextAttributeTextColor,
[UIFont systemFontOfSize:18.0f], UITextAttributeFont,
nil]];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:[UIColor whiteColor]];
I believe the code to change the navigation bar color is this:
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
This is for changing the colours of the navigation bar buttons in iOS 7, if you might need it:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
And this is the code if you want to change the colours of the buttons in iOS 6:
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
This code is also for iOS 8+ to change the bar button text color for UIActivityViewController activities (like sharing via Messages or Mail Composer).
I found a solution to change the text color of the Send and Cancel buttons.
Check my answer from here.
Regarding changing the status bar style from black to white, I've tried pretty much everything that is on Stackoverflow and nothing worked. There seems to be no workaround it.
One thing that might work, but I don't really know how to use it, could be changing the status bar style in the child view controller. There's a Stackoverflow post about it here.
This might work only if the assumption that the MFMailComposerViewController and MFMessageComposeViewController are child view controllers of UIActivityViewController and therefore if we specify the status bar style for the UIActivityViewController then the child view controllers should have the same status bar style as the parent.
There's a method in the UIViewController called childViewControllerForStatusBarStyle. Here is the Apple documentation for it .
But I don't really know how to use that. Did anyone figure this out?
You have to set the tintColor of the entire app.
self.window.tintColor = [UIColor redColor];
or
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
bar buttons
self.navigationController.navigationBar.tintColor = [UIColor redColor];

Change navigationBar appearance

My application flow: AViewController -> BViewController -> CViewController (via navigationController). AViewController and CViewController looks the same, only BViewController looks different.
I did it this way:
/// AppDelegate (should be 'super' settings)
[[UINavigationBar appearanceWhenContainedIn:[ABCNavigationController class], nil] setBackgroundImage:theImage forBarMetrics:UIBarMetricsDefault];
/// BViewController (should apply ONLY to BViewController)
[self.navigationController.navigationBar setBackgroundImage:BImage forBarMetrics:UIBarMetricsDefault];
The problem is that in CViewController i see the image i loaded in BViewController not in appDelegate. How to restore it to appDelegate settings?
I should underline that backgroundImage is one of many elements that i setup, gave it here as example.
In CViewController try setting the navbar's background image to nil in viewWillAppear, cause it reamains set by your BViewController.
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];

Change appearance of UINavigationBar from solid to transparent

I want to achieve the exact same effect as the Photos app on the iPad: solid black navigation bar during the gallery controller, then transparent when viewing a photo.
After I initialize my navigation controller in the AppDelegate I can change the style using the below code, but not outside the AppDelegate. However once the navigation controller is on screen and set once, navigationBar becomes a read-only property.
I would greatly appreciate if someone can share how this is done. Thanks.
self.navigationController.navigationBar.tintColor = [UIColor clearColor];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
UINavigationBar in UIBarStyleBlackTranslucent barStyle doesn't fix it's place as it normally does in other styles. In UIBarStyleBlackTranslucent style it just overlaps on your view and contents of views are translated up and view height is also increased.
if you're showing photos then first hide your navigationBar :
[[self navigationController] setNavigationBarHidden:YES animated:NO];
Now set your navBar's style to UIBarStyleBlackTranslucent
[self.navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
Then show your imageview (or scrollview with picture- depends on your logic). Then on tapping on your imageview you can show and hide bar)
// Show/Hide bar
// Let say you've a bool 'shown' for current status of navbar's visibility.
if (!shown) {
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}else{
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
shown = !shown;
Hope this'll do it. ANd never forget to rechnage barStyle to UIBarStyleBlackOpaque once you exit gallery.
Seems like you want to display navigationBar at the Gallery so there no need to change anything but after selecting a photo, keep the NavigationBar hidden in the PhotoViewController.
-(void) viewDidLoad
{
self.navigationController.navigationBar.barStyle=UIBarStyleBlackTranslucent;
self.navigationController.navigationBar.hidden = NO;
}
and in ViewWillAppear
-(void) viewWillAppear
{
self.navigationController.navigationBar.hidden = YES;
}
And then create a custom method implementing UITapGestureRecognizer where on a single tap display the navigationBar by setting hidden property to YES.

Does not autoresize when device is rotated after loading nibfromfile

I have the following question:
I got some code that gets called when an user logs in. The code has to call another view controller and has to show another view. To show to new view, i got the following code:
[scrollView removeFromSuperview];
Form1 *formcontroller1 = [[Form1 alloc] initWithNibName:#"Form1" bundle:[NSBundle mainBundle]];
[self.view setAutoresizesSubviews:YES];
[self.view addSubview:formcontroller1.view];
[scrollView release];
The problem is, when the other view is loaded and i rotate the device, the view of the new nib is not resizing correctly.
EDIT:
I wasn't dismissing the current viewcontroller so some properties remained. What i did is this:
[scrollView removeFromSuperview];
[self dismissModalViewControllerAnimated:YES];
Form1 *formcontroller = [[Form1 alloc] init];
[self presentModalViewController:formcontroller animated:YES];
[scrollView release];
You should check the autoresizing properties of your nib view in Interface Builder...
It should look like in the picture:
The middle arrows are dimmed, but still active. This is where autoresizing is set. You could try and set that property programmatically by assigning in your controller viewDidLoad method:
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
You should also ensure that both your view and its superviewhave the "autoresize subviews" button checked (in the first pane of the inspector in IB)
OLD ANSWER:
How is Form1 – shouldAutorotateToInterfaceOrientation: defined?
By default, this method returns YES for the UIInterfaceOrientationPortrait orientation only. If your view controller supports additional orientations, override this method and return YES for all orientations it supports.
Your implementation of this method should simply return YES or NO based on the value in the interfaceOrientation parameter. Do not attempt to get the value of the interfaceOrientation property or check the orientation value reported by the UIDevice class. Your view controller is either capable of supporting a given orientation or it is not.
E.g.:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
to support all orientations.

Presenting a Modal View Controller hides the Navigation Bar

I have a navigation based app with a navigation bar, but there are a few instances where instead of pushing a view controller onto the stack, I need to present the view controller modally. The problem is that when I dismiss the modal view controller, everything functions as expected except that the navigation bar is hidden and the (parent view) has been resized, which is the expected behavior according to the docs. So I figured I could simply call a built-in method to unhide the navigation bar. I have already tried
[self.navigationController setNavigationBarHidden:NO];
as well as the animated version without success.
The documentation talks about this in the method
presentModalViewController: animated:
in the discussion section where it says,
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen" and "Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy."However, the docs didn't clue me in as to how to undo this process after dismissing a modal view.
Has anyone else experienced this and found a solution?
Edit: I am having this same problem, so instead of asking my own question I am sponsoring a bounty on this one. This is my specific situation:
In my case, I am presenting an Image Picker in a Modal View Controller, over a Navigation Controller:
-(void) chooseImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagepicker = [[UIImagePickerController alloc] init];
imagepicker.allowsEditing = NO;
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.navigationBar.opaque = true;
imagepicker.wantsFullScreenLayout = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (self.view.window != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];
[popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {}
} else {
[self.navigationController presentModalViewController:imagepicker animated:YES];
}
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
//Save the image
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
}
Make sure you a presenting AND dismissing the modalViewController from the UINavigationController, like so:
// show
[self.navigationController presentModalViewController:vc animated:YES];
// dismiss
[self.navigationController dismissModalViewControllerAnimated:YES];
If your view controller is actually on the UINavigationController's stack then this is the correct way to handle the presentation and dismissal of the modal view controller. If your UINavigationBar is still hidden, there is something else funky going on and we would need to see your code to determine what is happening.
Edit
I copied your code into an app of mine and the UIImagePickerController successfully presented and dismissed and my UINavigationController's UINavigationBar was still there. I truly believe that the problem lays elsewhere in your architecture. If you upload a zip w/ an example project I will take a look.
Simply try following code it will work
SettingsViewController *settings = [[SettingsViewController alloc] init];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:settings];
[self presentModalViewController:navcont animated:YES];
[settings release];
[navcont release];
One need to present the navigation controller in order to have navigation bar on the presented controller
I think I've seen this behavior when presenting a view controller on the wrong VC. Are you calling presentModalViewController on the navigation controller or the individual VC?
Try calling it from the navigationController if you aren't already.
[self.navigationController presentModalViewController:myVC animated:YES];
If you present a controller as model, View controller will appear to total view.
If you want to access the navigation controller properties over the model view, You need to create another navigation controller reference and it continues as previous.
This may be useful for you.
Check this out. This is Apple's Documentation under UIViewController Class Reference:
It clearly mentions that modal view always presents in full screen mode, so it is obvious that navigation bar will be hidden. So put the seperate navigation bar on modal view to navigate back.
presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user.
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Parameters
modalViewController
The view controller that manages the modal view.
animated
If YES, animates the view as it’s presented; otherwise, does not.
Discussion
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen. On iPad, the presentation depends on the value in the modalPresentationStyle property.
Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy. The view is animated according to the transition style specified in the modalTransitionStyle property of the controller in the modalViewController parameter.
Availability
Available in iOS 2.0 and later.
Hope this helps you understand that hiding the whole view along with navigation controller is default behaviour for modal view so try putting a seperate navigation bar in modal view to navigate.
You can check it further on this link
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
AddContactVC *addController =[self.storyboard instantiateViewControllerWithIdentifier:#"AddContactVC"];
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];
working for me shows navigation bar
Emphatic and Devin –
As I started reading through the Apple docs to get familiar with the problem, I noticed that the method you're using, presentModalViewController:animated:, appears to be deprecated in favor of presentViewController:animated:completion:. Perhaps you should try to use that method instead.
For your convenience, take a look for yourself:
presentModalViewController:animated: reference
I'll try to put together a quick test program to see whether what I've said above is actually true. But give it a shot – maybe it'll help!
Xcode has a template that does pretty close to what you're doing. from the results, i don't think you should be attempting to perform [self.navigationController presentModalViewController:vc] and [self.navigationController dismissModalViewControllerAnimated:] , but rather simply [self presentModalViewController:] and [self dismissModalViewControllerAnimated:] .
to see how the template does this for yourself, you can use the new project wizard in xcode 4.3 . perhaps it will provide some guidance:
from that choice, choose Next, then give your test project a name, choose "Universal", turn off automatic reference counting, hit next, save where you want it.
now, click on the target and switch the deployment target to 4.3 (or 4.0 if you prefer) for your testing purposes, and switch to your device or the iOS 4.3 simulator .
finally, substitute the following code in applicationDidFinishLaunching:withOptions: in the created AppDelegate.m:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPhone"
bundle:nil] autorelease];
} else {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPad"
bundle:nil] autorelease];
}
UINavigationController* navigationController
= [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
now, when i run this, it doesn't hide the navigationBar. and in the created MainViewController.m from the template, you'll see how it presents the modal view controller and dismisses it from the controller itself and not from the navigation controller. for good measure, to make the template code more like your own, go into MainViewController.m and delete the line that sets the modal view controller transition style ...
(of course, in iOS 5, with storyboards, the same thing can all be accomplished with modal segues ... which is how i've done this for apps that i'm not supporting for pre-5.0 that present a modalViewController in this fashion.)
One of the best solution it to use this Category MaryPopin
https://github.com/Backelite/MaryPopin