使用smtp连接发送邮件时显示等待视图?
我正在使用邮件核心引擎发送邮件的应用程序。我创建了自己的viewController来发送邮件。我想在邮件发送过程中显示等待视图。邮件发送完成后,我的等待视图始终显示。这是一种线程问题吗?使用smtp连接发送邮件时显示等待视图?
这是我用来发送邮件的代码。
- (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;
}
好吧,谢谢你提供的所有信息。问题现在已经解决了。
我在这里张贴我的代码,以防万一有人需要它。
- (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];
}
是的。您需要返回到运行循环才能更新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
});
});
这不是因为它应该是。我现在已经更新了我的代码,请建议如何执行此操作。 – 2011-05-27 12:20:58
另外我无法在后台线程中发送邮件。我应该使用NSOPeration Queue吗? – 2011-05-27 12:24:15
来自apple文档: performSelector:方法等同于直接向接收方发送aSelector消息。 所以你现在还没有正在做任何多线程。我建议改变performSelector:@selector(prepareAndSendMail)来执行SelectorInBackground:然后请给出关于失败的更多细节。 – 2011-05-27 15:38:29
因为你是在主线程上执行prepareAndSendMail
,WNAppDelegate performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];
将在当前运行的循环已经结束到那时你会发送邮件后打电话showWaitingView
。将waitUntilDone:
设置为YES
将在您打算时显示等待视图。
将该标志设置为yes仍然不起作用。 – 2011-05-27 13:36:05
有没有在后台执行的原因?奇怪的是,因为我们在主线程中,所以可以简化为'[WNAppDelegate showWaitingView];' – 2011-05-27 20:43:23
是的,因为使用smtp发送邮件不能在后台执行。 – 2011-05-28 03:09:28
您是否将UI更新移动到后端线程? – 2011-05-30 06:25:12
否我已经将UI更新移动到不在后台线程中的另一个线程,并且按预期工作。首先,它给了我NSAutoreleas池泄漏的警告,但是当我将代码放入autorelease池时,警告不在我已经在gdb中测试过的地方。 – 2011-05-30 06:39:28
有很多地方明确喊UIKit更新只能在主线程中完成,就像[this]一样(http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/Introduction/ Introduction.html)。所以有可能会在稍后突破。 – 2011-05-30 06:48:18