dia*_*nna 9 iphone objective-c ios
我已经查看过相关问题,但没有解决我的问题.
我试图使用dismissViewControllerAnimated:animated:completion和presentViewControllerAnimated:animated:completion连续.使用故事板,我通过部分卷曲动画模拟呈现InfoController.
部分卷曲显示我想要启动的InfoController上的按钮MFMailComposeViewController.因为部分卷曲部分隐藏了MFMailComposeViewController,我首先要通过取消动画部分卷曲来解除InfoController.然后我想要MFMailComposeViewController动画片.
目前,当我尝试这个时,部分卷曲没有动画,但是MFMailComposeViewController没有得到呈现.我也有一个警告:
警告:尝试在InfoController上显示MFMailComposeViewController:其视图不在窗口层次结构中!
InfoController.h:
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
@interface InfoController : UIViewController <MFMailComposeViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UIButton *emailMeButton;
-(IBAction)emailMe:(id)sender;
@end
Run Code Online (Sandbox Code Playgroud)
InfoController.m
#import "InfoController.h"
@interface InfoController ()
@end
@implementation InfoController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)emailMe:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
[self sendMeMail];
}];
}
- (void)sendMeMail {
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
if([MFMailComposeViewController canSendMail]){
if(mailController)
{
NSLog(@"%@", self); // This returns InfoController
mailController.mailComposeDelegate = self;
[mailController setSubject:@"I have an issue"];
[mailController setMessageBody:@"My issue is ...." isHTML:YES];
[self presentViewController:mailController animated:YES completion:nil];
}
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
{
if (result == MFMailComposeResultSent) {
NSLog(@"It's sent!");
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Run Code Online (Sandbox Code Playgroud)
此外,如果我注释掉[self dismissViewControllerAnimated:YES completion:^{}];in (IBAction)emailMe,MFMailComposeViewController动画,但它部分隐藏在部分卷曲后面.我怎样才能首先解除卷曲然后在MFMailComposeViewController?
非常感谢!
编辑:如果我发表评论,下面是视图的图像 [self dismissViewControllerAnimated:YES completion:^{}];
auc*_*uco 19
这是视图控制器之间的通信问题,由于父子视图控制器关系不明确而导致......如果不使用协议和委派,这将无法正常工作.
经验法则是:
(听起来很无情,但如果你考虑的话,这是有意义的).
转换为ViewController关系:呈现视图控制器需要了解其子视图控制器,但子视图控制器必须不知道其父(呈现)视图控制器:子视图控制器使用其委托将消息发送回其(未知)父节点.
如果必须在标头中添加@Class声明来修复链式#import编译器警告,那么就知道出了问题.交叉引用总是一件坏事(顺便说一下,这也是委托应该始终(分配)而永远(强)的原因,因为这会导致交叉引用循环和一组僵尸)
那么,让我们看看你的项目的这些关系:
正如你没说的那样,我假设调用控制器名为MainController.所以我们将:
所以你想拥有这个:
子控制器定义一个协议,并且具有符合其协议的未指定类型的委托(换句话说:委托可以是任何对象,但它必须具有这一个方法)
@protocol InfoControllerDelegate
- (void)returnAndSendMail;
@end
@interface InfoControllerDelegate : UIViewController // …
@property (assign) id<InfoControllerDelegate> delegate
// ...
@end
Run Code Online (Sandbox Code Playgroud)
...并且MainController同时采用InfoControllerDelegate和MFMailComposeDelegate协议,因此它可以再次关闭MFMailComposer(注意,这不会也可能不需要是强大的属性,只是在这里显示它以使其清楚)
@interface MainController <InfoControllerDelegate, MFMailComposeViewControllerDelegate>
@property (strong) InfoController *infoController;
@property (strong) MFMailComposeViewController *mailComposer;
Run Code Online (Sandbox Code Playgroud)
// however you get the reference to InfoController, just assuming it's there
infoController.delegate = self;
[self presentViewController:infoController animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)
'infoController.delegate = self'是至关重要的一步.这使infoController有可能在不知道ObjectType(Class)的情况下将消息发送回MainController.不需要#import.它只知道,它是一个具有方法-returnAndSendMail的对象; 这就是我们需要知道的全部内容.
通常你会用alloc/init创建你的viewController,并让它懒洋洋地加载它的xib.或者,如果您正在使用Storyboards和Segues,您可能希望拦截segue(在MainController中)以便以编程方式设置委托:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// hook in the segue to set the delegate of the target
if([segue.identifier isEqualToString:@"infoControllerSegue"]) {
InfoController *infoController = (InfoController*)segue.destinationViewController;
infoController.delegate = self;
}
}
Run Code Online (Sandbox Code Playgroud)
按下eMail按钮时,将调用委托(MainController).请注意,self.delegate是MainController并不重要,它与此方法相关--returnAndSendMail
- (IBAction)sendEmailButtonPressed:(id)sender {
// this method dismisses ourself and sends an eMail
[self.delegate returnAndSendMail];
}
Run Code Online (Sandbox Code Playgroud)
...在这里(在MainController中!),你将解散InfoController(清理,因为它是MainController的责任)并呈现MFMailController:
- (void)returnAndSendMail {
// dismiss the InfoController (close revealing page)
[self dismissViewControllerAnimated:YES completion:^{
// and present MFMailController from MainController
self.mailComposer.delegate = self;
[self presentViewController:self.mailComposer animated:YES completion:nil];
}];
}
Run Code Online (Sandbox Code Playgroud)
所以,你使用MFMailController做的事情几乎和InfoController一样.两者都有他们未知的代表,所以他们可以回复消息,如果他们这样做,你可以解雇他们并继续你应该做的任何事情.
对这个,
- (IBAction)emailMe:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
[self sendMeMail];
}];
}
Run Code Online (Sandbox Code Playgroud)
关闭self viewController 后,您无法从 self 呈现视图控制器。
那你能做什么呢?
1)改变按钮按下方式,
- (IBAction)emailMe:(id)sender {
[self sendMeMail];
}
Run Code Online (Sandbox Code Playgroud)
2)当mailViewController被关闭时,您可以关闭self viewController。
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
{
if (result == MFMailComposeResultSent) {
NSLog(@"It's sent!");
}
[controller dismissViewControllerAnimated:NO completion:^ {
[self dismissViewControllerAnimated:YES completion:nil];
}];
}
Run Code Online (Sandbox Code Playgroud)