Changing the title of a MFMailComposeViewController - iphone

Although i know changing MFMailComposeViewController is fround upon, i'm taking a risk.
I found some ideas such as
[self presentModalViewController:controller animated:YES]; // Existing line
[[[[controller viewControllers] lastObject] navigationItem] setTitle:#"SomethingElse"];
and
[[[[(MFMailComposeViewController*)vc navigationBar] items] objectAtIndex:0] setTitle:#" SomethingElse"];
but the odd thing is that the title is "SomethingElse" for like 2 seconds and after that it returns to the subject that is set. I've tried other solutions as well but the same output.
I am using SHK (ShareKit) to connect to social. Here is the code from showViewController :
if ([vc respondsToSelector:#selector(modalPresentationStyle)])
vc.modalPresentationStyle = [SHK modalPresentationStyle];
if ([vc respondsToSelector:#selector(modalTransitionStyle)])
vc.modalTransitionStyle = [SHK modalTransitionStyle];
[topViewController presentModalViewController:vc animated:YES];
[[[[(MFMailComposeViewController*)vc navigationBar] items] objectAtIndex:0] setTitle:#" "];
[(UINavigationController *)vc navigationBar].barStyle =
[(UINavigationController *)vc toolbar].barStyle = [SHK barStyle];
self.currentView = vc;

I believe this is some kind of protection came with iOS4.
It is clearly stated here that you MUST NOT change the interface provided by Apple.
http://developer.apple.com/library/ios/#documentation/MessageUI/Reference/MFMailComposeViewController_class/Reference/Reference.html
Important: The mail composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is not allowed to make further changes to the email content. The user may still edit the content using the interface, but programmatic changes are ignored. Thus, you must set the values of content fields before presenting the interface.
I knew some people being rejected because of this. I just wanted to warn you about this.

You just need to set the mail subject. Means [MFMailComposeViewController setsubject:#"yourTitle"]. Then this will be shown as a titile .but if you do not write anything in MFMailComposeViewController subject then by default it can show "New Message".

Related

Initial text and paperclipped-URL for action in UIActivityViewController & UIActivityItemSource?

Finally been making it through Apple's (rather dismal) documentation on the new UIActivityViewController class and the UIActivityItemSource protocol, and I'm trying to send different data sets to different actions called from the activity view. To simplify things, I'm looking at two things.
A Facebook posting action, which should say "Check this out!" and also attach a URL to the post (with that cute little paperclip).
A Twitter posting action, which should say "Check this out, with #hashtag!" and also attach that same URL (with the same paperclip).
Here's the code I've got implemented right now.
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
return #"Check this out!";
} else if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
return #"Check this out, with #hashtag!";
}
return #"";
}
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController {
return #"";
}
And then when I set up this activity view controller (it's in the same class), this is what I do.
UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:#[self] applicationActivities:nil];
[self presentViewController:activityView animated:YES completion:nil];
My dilemma is how to attach that NSURL object. It's relatively easy when calling the iOS 6 SL-class posting modals; you just call the individual methods to attach a URL or an image. How would I go about doing this here?
I'll note that instead of returning NSString objects from -activityViewController:itemForActivityType, if I return just NSURL objects, they show up with that paperclip, with no body text in the post. If I return an array of those two items, nothing shows up at all.
Evidently it was as simple as this: passing in an array to the first argument of UIActivityViewController's init call, with each item in the array handling a different data type that will end up in the compose screen. self handles the text, and the second object (the NSURL) attaches the URL.
NSArray *items = #[self, [NSURL URLWithString:#"http://this-is-a-url.com"]];
UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[self presentViewController:activityView animated:YES completion:nil];
Really wish there was more on this, but here it is.

removeFromSuperView is not working in iPad2 with iOS5

I have a little issue from removeFromSuperView as it's not at least working with iPad2 with iOS 5. I'm displaying a custom UIView alert before my table populates with data and once done, I'm removing it from the super view. with every other device it's working fine except in iPad2 (iOS5). Am I missing anything?
.h
#private
SaveUIDisplayViewController *wbsSummaryLoadView;
.m
// Displaying
wbsSummaryLoadView = [[SaveUIDisplayViewController alloc] initWithNibName:#"SaveUIDisplayViewController" bundle:nil];
[[wbsSummaryLoadView view] setFrame:[self view].bounds];
[wbsSummaryLoadView setupSavingViewWithTitle:NSLocalizedString(#"Loading...", #"")];
[[self view] addSubview:wbsSummaryLoadView.view];
// Removing
[wbsSummaryLoadView.view removeFromSuperview];
[wbsSummaryLoadView release];
wbsSummaryLoadView = nil;
Once you add a view you can release it right away. (a copy is creating by using addSubview)
Try:
[[self view] addSubview:wbsSummaryLoadView.view];
[wbsSummaryLoadView release];
and then you don't need to care, because if you release whole view you release that added view as well.
You are storing two different objects. When you create the SaveUIDisplayViewController, you are declaring a new instance in that method. When you are removing it, you are using (I guess) the member variable.
SaveUIDisplayViewController *wbsSummaryLoadView = [[SaveUIDisplayViewController alloc] initWithNibName:#"SaveUIDisplayViewController" bundle:nil];
This will hide any declaration of wbsSummaryLoadView that you have defined in the header of the object.
And when you come to remove it
[wbsSummaryLoadView.view removeFromSuperview];
Has to have wbsSummaryLoadView declared somewhere so (this is where I'm guessing as you haven't posted your .h file) if this is declared in the header, then it won't be the same as the one when you created it (in fact it will probably be nil at this point)

UIPopoverController memory question

I'm creating a UIPopoverController and setting "Editor1" as the content view controller.
When the caller receives the didDismissPopover I'm releasing the UIPopoverController.
This is the code:
- (IBAction)open1:(id)sender {
Editor1 *editor = [[Editor1 alloc] initWithNibName:#"Editor1" bundle:nil];
_popoverController = [[UIPopoverController alloc] initWithContentViewController:editor];
_popoverController.delegate = self;
[editor release];
[self.popOverController presentPopoverFromRect:self.open1Button.bounds inView:self.open1Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
NSLog(#"popoverControllerShouldDismissPopover");
return YES;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{
NSLog(#"popvoerControllerDidDismissPopover");
[_popoverController release];
}
In my editor I have a UITextField where the user changes text and I save it when I get the message "editingDidEnd"
- (IBAction)editingDidEnd:(id)sender {
NSLog(#"Editing did End");
// SAVE PROCEDURE
}
My question regards the order in which the methods get called.
The order is:
2011-09-07 12:35:21.628 iosTest[1967:b603] popoverControllerShouldDismissPopover
2011-09-07 12:35:21.629 iosTest[1967:b603] popvoerControllerDidDismissPopover
2011-09-07 12:35:21.983 iosTest[1967:b603] Editing did End
2011-09-07 12:35:21.985 iosTest[1967:b603] viewWill Disappear
As you can see the popoverControllerDidDismissPopover gets called before editingDidEnd:, so this means I'm releasing the popover before I do my save procedure. This could bring me a crash problem.
Also, in my save procedure I need to ask the user for confirmation in some cases. I'm using a UIAlertView for this.
Do you have any recommendations?
Usually views are well-behaved and don't send events after they're off-screen. You can check for potential problems by enabling zombies (set the environment variable NSZombieEnabled=YES).
If there is a crash, the correct place to fix it is in -[Editor1 dealloc] (and possibly -viewDidUnload): just do textField.delegate = nil and you should stop receiving callbacks. This is not usually necessary except for web views and scroll views where it seems to be problematic (the scroll animation continues even if the VC is off-screen).
In your case, you can probably make saving happen in -popoverControllerShouldDismissPopover:, returning NO if you need to display a UIAlertView (and dismissing the popover when the button is pressed).
it seems, that _popoverController is the instance-property. in this case you can release it in viewDidUnload method of parent-controller.
Why don't you use UITextFieldDelegate protocol? Usage:
aTextField.delegate = self;
(...)
- (void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(#"Editing did End");
// SAVE PROCEDURE
}
Read the documentation for more info.

How to set title in the MFMailComposerViewController?

I am trying to set the title of MFMailComposerViewController , which is a subclass of UINavigationController.
I am using these following ways :
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
[picker.navigationController navigationItem].title = #"Send Mail";
[[picker navigationItem] setTitle:#"Send Mail"];
But I am not able to set the Title.
Am i doing it wrong ??
Is there any other method to do so ??
Thanks
The title is updated whenever the subject changes. You cannot change the title programmatically within AppStore restrictions. You may use -setSubject: to initialize the subject.
(A bad way to solve this is to create a very high-level window with a label that covers original title. This is very difficult to make this work with orientation change.)

Set First Responder in MFMailComposeViewController?

I'm using Apple's MailComposer example application to send email from within my application (OS 3.0 functionality). Is it possible to set the To, Subject, or Body fields as first responder with MFMailComposeViewController?
In other words, the behavior would be: the user presses a button which presents the mail view (presentModalViewController). When the mail view is presented, the cursor is placed in one of the fields and the keyboard opens.
I notice the MFMailComposeViewController documentation says:
"Important: The mail composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is not allowed to make further changes to the email content. The user may still edit the content using the interface, but programmatic changes are ignored. Thus, you must set the values of content fields before presenting the interface."
However, I don't care about customizing the interface. I just want to set that firstResponder. Any ideas?
You are able to make these fields become the first responder.
if you add the following method to your class...
//Returns true if the ToAddress field was found any of the sub views and made first responder
//passing in #"MFComposeSubjectView" as the value for field makes the subject become first responder
//passing in #"MFComposeTextContentView" as the value for field makes the body become first responder
//passing in #"RecipientTextField" as the value for field makes the to address field become first responder
- (BOOL) setMFMailFieldAsFirstResponder:(UIView*)view mfMailField:(NSString*)field{
for (UIView *subview in view.subviews) {
NSString *className = [NSString stringWithFormat:#"%#", [subview class]];
if ([className isEqualToString:field])
{
//Found the sub view we need to set as first responder
[subview becomeFirstResponder];
return YES;
}
if ([subview.subviews count] > 0) {
if ([self setMFMailFieldAsFirstResponder:subview mfMailField:field]){
//Field was found and made first responder in a subview
return YES;
}
}
}
//field not found in this view.
return NO;
}
Then, after you present the MFMailComposeViewController, pass the MFMailComposeViewController's view into the function along with the field you want to become first responder.
MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
/*Set up the mail composer*/
[self presentModalViewController:mailComposer animated:YES];
[self setMFMailFieldAsFirstResponder:mailComposer.view mfMailField:#"RecipientTextField"];
[mailComposer release];
In iOS 6, it is no longer possible to set first responder on any of the text fields AFAICT. Navigating the view hierarchy eventually reveals a UIRemoteView and the subviews within here are obfuscated away.
You can try just calling becomeFirstResponder on the controller itself. If that doesn't work, you can try in the debugger getting the list of subviews of the mail compose view until you find a familiar textfield or textview which you can then code specifically to set the responder status in code, which might look something like this (i don't know if this will work but it's an example):
[[[[mailcomposer.view.subviews objectAtIndex:3] subviews] objectAtIndex:2] becomeFirstResponder]
I like to simplify the code and make it easy to understand.
Just put the follow code after:
[self presentModalViewController:mailComposer animated:YES];
for (UIView *subview in mailComposer.view.subviews) {
NSString *className = [NSString stringWithFormat:#"%#", [subview class]];
//NSLog(#"%#", className); // list the views - Use this to find another view
//The view I want to set as first responder: "_MFMailRecipientTextField"
if ([className isEqualToString:#"_MFMailRecipientTextField"]){
[subview becomeFirstResponder];
break; // Stop search.
}
}