iOS-如何在代码开始之前显示 alertView

Posted

技术标签:

【中文标题】iOS-如何在代码开始之前显示 alertView【英文标题】:iOS- How to show alertView before code starts 【发布时间】:2012-07-19 01:48:13 【问题描述】:

我有以下代码:

-(IBAction)showAlertView:(id)sender

alertView = [[UIAlertView alloc] initWithTitle:@"Atualizando" message:@"\n"delegate:self cancelButtonTitle:nil otherButtonTitles:nil];

spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];   
spinner.center = CGPointMake(139.5, 75.5); // .5 so it doesn't blur
[alertView addSubview:spinner];
[spinner startAnimating];
[alertView show]; 



-(IBAction)getContacts:(id)sender 

[self showAlertView:(id)self];

ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

我想在 IBAction 的其余部分开始之前显示警报,但我只在 IBAction 结束时看到 alertView。我做错了什么?

编辑:我有:

-(IBAction)getContacts:(id)sender 

// display the alert view
[self showAlertView:self];

// do the synchronous operation on a different queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^

ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

....

if ([contact length] == 8) 

            NSString *first = (NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
            NSString *last = (NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
            NSString *phone = contact;
            ContactInfo *user1 = [[ContactInfo alloc] init];
            user1.first = first;
            user1.last = last;
            user1.phone = phone;
            user1.person = person;
            user1.phoneIdx = j;
            user1.book = addressBook;
            NSLog(@"phone is %@", phone);
            [secondViewController.users addObject:user1];
        
        ABRecordSetValue(person, kABPersonPhoneProperty, mutablePhones, &error);
    

bool didSave = ABAddressBookSave(addressBook, &error);
if(!didSave)
    NSLog(@"error!");

dispatch_async(dispatch_get_main_queue(), ^
    [self hideAlertView]; // or however you want to do it
);

UIAlertView *alertAlmost = [[UIAlertView alloc] initWithTitle:@"Quase Pronto" message:@"Os seguintes contatos não tem código de área. Porfavor, selecione os contatos que você deseja adicionar o digito 9 e pressione Ok (caso não queira adicionar em nenhum, pressione Ok) " delegate:self cancelButtonTitle:@"Ok!" otherButtonTitles:nil];
[alertAlmost show];

[self presentViewController: secondViewController animated:YES completion: NULL];
 );

我希望解除警报,然后我可以调用表格视图。有什么建议吗?

【问题讨论】:

【参考方案1】:

显示UIAlertView 是异步完成的,因此如果您在方法顶部调用showAlertView:,它将显示警报视图,然后立即返回,然后执行您的方法的其余部分。

如果您希望在关闭警报视图后执行其余方法,则需要将自己添加为警报视图的delegate,然后实现该方法

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex

然后在里面做剩下的事情。


编辑:好的,我想我明白你的问题了。您正在对主队列执行一些耗时的同步操作,这会阻塞它,以便稍后才会显示警报视图。

您应该像这样将耗时的操作移到不同的队列中:

-(IBAction)getContacts:(id)sender 
    // display the alert view
    [self showAlertView:self];

    // do the synchronous operation on a different queue
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
        ABAddressBookRef addressBook = ABAddressBookCreate( );
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
        CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

        // once this operation has finished, you can hide the alert view like so:
        dispatch_async(dispatch_get_main_queue(), ^
            [self hideAlertView]; // or however you want to do it
        );
    );

【讨论】:

我不希望这样,我希望在代码运行时显示警报,并在我关闭后显示 这不正是异步的意思吗? 到底是什么问题?您试图在其他事情发生时显示警报视图(例如“正在加载...”视图或其他内容),但其他事情首先发生?我认为你的问题是你的通讯录调用阻塞了你的主线程,而不是让它绘制 UIAlertView。我会在几秒钟内更新我的答案。 可能是- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)waitYES 而不是[self showAlertView:(id)self],你应该叫它[self performSelectorOnMainThread:@selector(showAlertView:) withObject:(id) self waitUntilDone:YES];【参考方案2】:

当您的警报被解除时,您需要执行“getContacts:”中的其余代码。在“self”(显示警报的视图控制器)的 UIAlertView 上设置一个委托,然后在用户单击按钮以关闭警报时执行“addressBook”操作。

例如,实现 UIAlertViewDelegate 方法 alertView:clickedButtonAtIndex: 并在其中处理您的通讯录(我为您链接了文档)。

【讨论】:

我不希望这样,我希望在代码运行时显示警报,并在我关闭后显示 然后分离一个单独的(后台)线程,并在您的警报可见并且在它被解除后以单独的方法处理您的地址簿内容。如果这不能回答您的问题,那么您的原始问题可能对我们来说有点太混乱了。 ;-)【参考方案3】:

我想你是说你想弹出一个提醒,比如一个进度指示器,并且提醒出现时,你想开始你的另一个过程。目前,您请求立即显示警报,但正如其他答案所说,该调用是异步的,并且 UI 线程无法在开始其他工作之前显示警报。

你可以试试这个:

-(IBAction)getContacts:(id)sender 

    [self showAlertView:(id)self];
    [self performSelectorInBackground: @selector(initAddressBook) withObject: nil];


-(void)initAddressBook 
    ABAddressBookRef addressBook = ABAddressBookCreate( );
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
    CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

如果在后台运行地址簿工作时出现问题,您甚至可以给 UI 线程足够的时间来发布警报,如下所示:

-(IBAction)getContacts:(id)sender 

    [self showAlertView:(id)self];
    [self performSelector: @selector(initAddressBook) withObject: nil afterDelay: 0.1f];

【讨论】:

这可能比我的 GCD 解决方案更 Cocoa-ish,但我的 GCD 解决方案具有可读性的优势,因为一切都以一种方法以线性方式发生,而不是四处走动。 (在这种情况下,您必须使用另一种方法来关闭警报视图并使用另一个performSelector... 调用)。不过,这将完全有效。 @Anshu,我完全不同意 GCD 更具可读性。我自己一直都在使用 GCD,它是工具包中的一个很好的工具。但是,当发布似乎由更多初级 Obj-C 程序员提出的问题的答案时,我认为建议不要将它们引导到 GCD 中,除非需要 GCD 提供的上述和超越传统的 Obj-C 接口。而这个问题并不构成这样的需要。 我个人觉得它更具可读性,但我想这是一个见仁见智的问题。我绝对同意这不适合对 ObjC 这么陌生的人,而且当我写答案时我并没有真正考虑到这一点,所以感谢您指出这一点。 @Anshu,你是对的......可读性总是有点主观。我不认为你的回答不恰当。而且我可能错了海报是 Obj-C 的新手(尽管我打赌他是)。这就是堆栈溢出的美妙之处。解决问题的方法通常不止一种,最好能得到能告诉你所有选择的答案。无论如何,我没有发布我的答案,因为我认为 GCD 是一个 bad 选择......在我写它的时候,你还没有添加你的编辑,所以原来的问题仍然是未解决...仅此而已:)

以上是关于iOS-如何在代码开始之前显示 alertView的主要内容,如果未能解决你的问题,请参考以下文章

在 IOS7 中不可见 AlertView 上的选择器

当 Push Notification AlertView 出现在视图上时如何突出显示特定的视图区域?

在 ios 9 中快速使用 alertview

如何在 iOS 中处理多个 UIAlertController?

关于 iOS7 中的 AlertView App Crash

iOS 8 显示 UIView 的问题