使用 smtp 连接 ios 发送邮件时显示等待视图?

发布于 2024-11-09 12:16:21 字数 2523 浏览 3 评论 0原文

我正在开发一个使用邮件核心引擎发送邮件的应用程序。我创建了自己的 viewController 来发送邮件。我想在邮件发送过程中显示等待视图。我的等待视图总是在邮件发送完成后显示。这是某种线程问题吗?

这是我用来发送邮件的代码。

- (IBAction) sendTapped:(id) sender {

[txtfSubject resignFirstResponder];
[txtfReceptient resignFirstResponder];
[txtvMessageBody resignFirstResponder];

[self setTo:txtfReceptient.text];
[self setFrom:username];
[self setSubject:txtfSubject.text];
[self setBody:txtvMessageBody.text];

[self performSelector:@selector(prepareAndSendMail) withObject:nil afterDelay:0.34];
}


- (void) prepareAndSendMail {


[WNAppDelegate performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];

//TODO: send mail here
CTCoreMessage *msg = [[CTCoreMessage alloc] init];
[msg setTo:[myMessage to]];
[msg setFrom:[myMessage from]];

//Encode message here
NSString *encodedMessage = nil;

@try {
    encodedMessage = [self encodeMessage:txtvMessageBody.text];
}
@catch (NSException * e) {
    NSLog(@"An exception occurred while encoding message");
}
@finally {
    if(encodedMessage){
        [msg setBody:encodedMessage];
    }
}

[msg setSubject:[myMessage subject]];

BOOL success =  [self sendMailOnAnotherThread:msg];

[msg release];

[WNAppDelegate performSelectorOnMainThread:@selector(removeWaitingView) withObject:nil waitUntilDone:NO];
//[appDelegate removeWaitingView];
if(!success) {
    UIAlertView * empty_alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                           message:@"Could not send." 
                                                          delegate:nil 
                                                 cancelButtonTitle:@"OK" 
                                                 otherButtonTitles:nil];
    [empty_alert show];
    [empty_alert autorelease];
    return;
}   
else {
    //Message sent successfully
    if(self.target && [self.target respondsToSelector:@selector(messageSentSuccessfully)]){
        [self.target messageSentSuccessfully];
    }

    WN_POST_NOTIFICATION(kMessageSentSuccessfully,nil);
}

[self dismissModalViewControllerAnimated:YES];  
 }

- (BOOL) sendMailOnAnotherThread:(CTCoreMessage*)message {


BOOL success = YES;

BOOL auth = YES;
BOOL tls = YES;

@try {
    [CTSMTPConnection sendMessage:message server:GMAIL_SERVER  username:username
                         password:password port:GMAIL_PORT_Number useTLS:tls useAuth:auth];
}
@catch (NSException * e) {
    //Msg failed to send;
    success = FALSE;
}
return success;     
}

I am working on a app in which I am sending mail using mail-core engine. I have created my own viewController to send mail. I want to show a waiting view when mail sending is in process. My waiting view always displays after mail sending has been done. Is it some kind of threading issue?

Here is the code which I'm using to send mail.

- (IBAction) sendTapped:(id) sender {

[txtfSubject resignFirstResponder];
[txtfReceptient resignFirstResponder];
[txtvMessageBody resignFirstResponder];

[self setTo:txtfReceptient.text];
[self setFrom:username];
[self setSubject:txtfSubject.text];
[self setBody:txtvMessageBody.text];

[self performSelector:@selector(prepareAndSendMail) withObject:nil afterDelay:0.34];
}


- (void) prepareAndSendMail {


[WNAppDelegate performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];

//TODO: send mail here
CTCoreMessage *msg = [[CTCoreMessage alloc] init];
[msg setTo:[myMessage to]];
[msg setFrom:[myMessage from]];

//Encode message here
NSString *encodedMessage = nil;

@try {
    encodedMessage = [self encodeMessage:txtvMessageBody.text];
}
@catch (NSException * e) {
    NSLog(@"An exception occurred while encoding message");
}
@finally {
    if(encodedMessage){
        [msg setBody:encodedMessage];
    }
}

[msg setSubject:[myMessage subject]];

BOOL success =  [self sendMailOnAnotherThread:msg];

[msg release];

[WNAppDelegate performSelectorOnMainThread:@selector(removeWaitingView) withObject:nil waitUntilDone:NO];
//[appDelegate removeWaitingView];
if(!success) {
    UIAlertView * empty_alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                           message:@"Could not send." 
                                                          delegate:nil 
                                                 cancelButtonTitle:@"OK" 
                                                 otherButtonTitles:nil];
    [empty_alert show];
    [empty_alert autorelease];
    return;
}   
else {
    //Message sent successfully
    if(self.target && [self.target respondsToSelector:@selector(messageSentSuccessfully)]){
        [self.target messageSentSuccessfully];
    }

    WN_POST_NOTIFICATION(kMessageSentSuccessfully,nil);
}

[self dismissModalViewControllerAnimated:YES];  
 }

- (BOOL) sendMailOnAnotherThread:(CTCoreMessage*)message {


BOOL success = YES;

BOOL auth = YES;
BOOL tls = YES;

@try {
    [CTSMTPConnection sendMessage:message server:GMAIL_SERVER  username:username
                         password:password port:GMAIL_PORT_Number useTLS:tls useAuth:auth];
}
@catch (NSException * e) {
    //Msg failed to send;
    success = FALSE;
}
return success;     
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

原野 2024-11-16 12:16:21

好的,谢谢你们提供的所有信息。现在问题已经解决了。

我在这里发布我的代码,以防有人需要。

- (IBAction) sendTapped:(id) sender {

[txtfSubject resignFirstResponder];
[txtfReceptient resignFirstResponder];
[txtvMessageBody resignFirstResponder];

[self setTo:txtfReceptient.text];
[self setFrom:username];
[self setSubject:txtfSubject.text];
[self setBody:txtvMessageBody.text];

[self performSelector:@selector(prepareAndSendMail) withObject:nil afterDelay:0.34];
}


- (void) prepareAndSendMail {

//[((WalnutAppDelegate*)WNAppDelegate) performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSThread *aNewThread = [[[NSThread alloc] initWithTarget:((WalnutAppDelegate*)WNAppDelegate) selector:@selector(showWaitingView) object:nil] autorelease];
[aNewThread start];


//[NSThread detachNewThreadSelector: toTarget:((WalnutAppDelegate*)WNAppDelegate) withObject:nil];

//TODO: send mail here
CTCoreMessage *msg = [[CTCoreMessage alloc] init];
[msg setTo:[myMessage to]];
[msg setFrom:[myMessage from]];

//Encode message here
NSString *encodedMessage = nil;

@try {
    encodedMessage = [self encodeMessage:txtvMessageBody.text];
}
@catch (NSException * e) {
    NSLog(@"An exception occurred while encoding message");
}
@finally {
    if(encodedMessage){
        [msg setBody:encodedMessage];
    }
}

[msg setSubject:[myMessage subject]];

BOOL success =  [self sendMailOnAnotherThread:msg];

[msg release];

//[NSThread detachNewThreadSelector:@selector(removeWaitingView) toTarget:((WalnutAppDelegate*)WNAppDelegate) withObject:nil];

[((WalnutAppDelegate*)WNAppDelegate) performSelectorOnMainThread:@selector(removeWaitingView) withObject:nil waitUntilDone:NO];
[pool drain];


if(!success) {
    UIAlertView * empty_alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                           message:@"Could not send." 
                                                          delegate:nil 
                                                 cancelButtonTitle:@"OK" 
                                                 otherButtonTitles:nil];
    [empty_alert show];
    [empty_alert autorelease];
    return;
}   
else {
    //Message sent successfully
    if(self.target && [self.target respondsToSelector:@selector(messageSentSuccessfully)]){
        [self.target messageSentSuccessfully];
    }

    WN_POST_NOTIFICATION(kMessageSentSuccessfully,nil);
}

[self dismissModalViewControllerAnimated:YES];  
}

- (BOOL) sendMailOnAnotherThread:(CTCoreMessage*)message {


BOOL success = YES;

BOOL auth = YES;
BOOL tls = YES;

@try {
    [CTSMTPConnection sendMessage:message server:GMAIL_SERVER  username:username
                         password:password port:GMAIL_PORT_Number useTLS:tls useAuth:auth];
}
@catch (NSException * e) {
    //Msg failed to send;
    success = FALSE;
}
return success;     
}

- (void)showWaitingView {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

CGRect frame = CGRectMake(90, 190, 32, 32);
UIActivityIndicatorView* progressInd = [[UIActivityIndicatorView alloc] initWithFrame:frame];
[progressInd startAnimating];
progressInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;

frame = CGRectMake(130, 193, 140, 30);
UILabel *waitingLable = [[UILabel alloc] initWithFrame:frame];
waitingLable.text = @"Processing...";
waitingLable.textColor = [UIColor whiteColor];
waitingLable.font = [UIFont systemFontOfSize:20];;
waitingLable.backgroundColor = [UIColor clearColor];
frame = [[UIScreen mainScreen] applicationFrame];
UIView *theView = [[UIView alloc] initWithFrame:frame];
theView.backgroundColor = [UIColor blackColor];
theView.alpha = 0.7;
theView.tag = 999;
[theView addSubview:progressInd];
[theView addSubview:waitingLable];

[progressInd release];
[waitingLable release];

[window addSubview:[theView autorelease]];
[window bringSubviewToFront:theView];
[pool drain];
}

- (void)removeWaitingView {
UIView *v = [window viewWithTag:999];
if(v) [v removeFromSuperview];

}

Ok guys,Thanks for all the info you have provided. The problem is now solved.

I'M posting here my code in case some one need it.

- (IBAction) sendTapped:(id) sender {

[txtfSubject resignFirstResponder];
[txtfReceptient resignFirstResponder];
[txtvMessageBody resignFirstResponder];

[self setTo:txtfReceptient.text];
[self setFrom:username];
[self setSubject:txtfSubject.text];
[self setBody:txtvMessageBody.text];

[self performSelector:@selector(prepareAndSendMail) withObject:nil afterDelay:0.34];
}


- (void) prepareAndSendMail {

//[((WalnutAppDelegate*)WNAppDelegate) performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSThread *aNewThread = [[[NSThread alloc] initWithTarget:((WalnutAppDelegate*)WNAppDelegate) selector:@selector(showWaitingView) object:nil] autorelease];
[aNewThread start];


//[NSThread detachNewThreadSelector: toTarget:((WalnutAppDelegate*)WNAppDelegate) withObject:nil];

//TODO: send mail here
CTCoreMessage *msg = [[CTCoreMessage alloc] init];
[msg setTo:[myMessage to]];
[msg setFrom:[myMessage from]];

//Encode message here
NSString *encodedMessage = nil;

@try {
    encodedMessage = [self encodeMessage:txtvMessageBody.text];
}
@catch (NSException * e) {
    NSLog(@"An exception occurred while encoding message");
}
@finally {
    if(encodedMessage){
        [msg setBody:encodedMessage];
    }
}

[msg setSubject:[myMessage subject]];

BOOL success =  [self sendMailOnAnotherThread:msg];

[msg release];

//[NSThread detachNewThreadSelector:@selector(removeWaitingView) toTarget:((WalnutAppDelegate*)WNAppDelegate) withObject:nil];

[((WalnutAppDelegate*)WNAppDelegate) performSelectorOnMainThread:@selector(removeWaitingView) withObject:nil waitUntilDone:NO];
[pool drain];


if(!success) {
    UIAlertView * empty_alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                           message:@"Could not send." 
                                                          delegate:nil 
                                                 cancelButtonTitle:@"OK" 
                                                 otherButtonTitles:nil];
    [empty_alert show];
    [empty_alert autorelease];
    return;
}   
else {
    //Message sent successfully
    if(self.target && [self.target respondsToSelector:@selector(messageSentSuccessfully)]){
        [self.target messageSentSuccessfully];
    }

    WN_POST_NOTIFICATION(kMessageSentSuccessfully,nil);
}

[self dismissModalViewControllerAnimated:YES];  
}

- (BOOL) sendMailOnAnotherThread:(CTCoreMessage*)message {


BOOL success = YES;

BOOL auth = YES;
BOOL tls = YES;

@try {
    [CTSMTPConnection sendMessage:message server:GMAIL_SERVER  username:username
                         password:password port:GMAIL_PORT_Number useTLS:tls useAuth:auth];
}
@catch (NSException * e) {
    //Msg failed to send;
    success = FALSE;
}
return success;     
}

- (void)showWaitingView {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

CGRect frame = CGRectMake(90, 190, 32, 32);
UIActivityIndicatorView* progressInd = [[UIActivityIndicatorView alloc] initWithFrame:frame];
[progressInd startAnimating];
progressInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;

frame = CGRectMake(130, 193, 140, 30);
UILabel *waitingLable = [[UILabel alloc] initWithFrame:frame];
waitingLable.text = @"Processing...";
waitingLable.textColor = [UIColor whiteColor];
waitingLable.font = [UIFont systemFontOfSize:20];;
waitingLable.backgroundColor = [UIColor clearColor];
frame = [[UIScreen mainScreen] applicationFrame];
UIView *theView = [[UIView alloc] initWithFrame:frame];
theView.backgroundColor = [UIColor blackColor];
theView.alpha = 0.7;
theView.tag = 999;
[theView addSubview:progressInd];
[theView addSubview:waitingLable];

[progressInd release];
[waitingLable release];

[window addSubview:[theView autorelease]];
[window bringSubviewToFront:theView];
[pool drain];
}

- (void)removeWaitingView {
UIView *v = [window viewWithTag:999];
if(v) [v removeFromSuperview];

}
停滞 2024-11-16 12:16:21

是的。您需要返回运行循环才能更新 UI。因此,最好在主线程中显示等待视图,在后台线程中发送邮件,然后再次在主线程中隐藏和删除等待视图。您应该只从主线程更新 UI。您可以使用performSelectorInBackground 和performSelectorOnMainThread 来轻松完成此操作,而无需手动创建线程。您还可以像这样使用dispatch_async:

//show waiting view
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //prepare mail here

    dispatch_async(dispatch_get_main_queue(), ^{
        //send mail
        //hide waiting view
    });
});

Yes it is. You need to return to run loop in order to get UI updated. So it is best to display the waiting view in main thread, send mail in background thread and then again hide and remove waiting view in main thred. You should only update UI from main thread. You can use performSelectorInBackground and performSelectorOnMainThread to do it the easy way without creating threads manually. You can also use dispatch_async like this:

//show waiting view
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //prepare mail here

    dispatch_async(dispatch_get_main_queue(), ^{
        //send mail
        //hide waiting view
    });
});
意犹 2024-11-16 12:16:21

由于您在主线程上执行 prepareAndSendMailWNAppDelegate PerformSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO]; 将调用 showWaitingView当前运行循环结束后,您将发送邮件。将 waitUntilDone: 设置为 YES 将在您想要的时间显示等待视图。

Since you are executing prepareAndSendMail on the main thread, WNAppDelegate performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO]; will call showWaitingView after the current run loop has ended by which time you will have sent the mail. Setting waitUntilDone: to YES will show the waiting view at the time you intend it to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文