问题描述
|
我正在开发一个使用邮件核心引擎发送邮件的应用程序。我创建了自己的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;
}
解决方法
好的,谢谢您提供的所有信息。现在问题已解决。
我在这里发布我的代码,以防有人需要它。
- (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
});
});
,由于您正在主线程上执行prepareAndSendMail
,因此在当前运行循环结束之后,WNAppDelegate performSelectorOnMainThread:@selector(showWaitingView) withObject:nil waitUntilDone:NO];
将调用showWaitingView
,此时您将已发送邮件。将waitUntilDone:
设定为YES
将显示您想要的等待时间。