我在这里有点困惑,我使用队列,我到了一点,我有点迷失。
我有一个名为getPeople
的方法,他必须从服务器上获取用户的图片。为了不阻止我使用的应用程序:
-(IBAction)seeMorePeople{
dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
dispatch_async(getPeopleQueue, ^{
[self getPeople];
});
dispatch_release(getPeopleQueue);
}
每次用户点击按钮时都会执行上一个代码。像“从这张专辑给我照片”然后另一个点击“现在我想要来自其他专辑的人物照片”,不同的照片和不同数量的照片。如果用户非常快地点击按钮,则第一个队列在第二个队列已经启动时不会完成获取数据。在getPeople
中,我将数据存储在NSMutableArray中,因此当两个队列同时执行时,两个队列都在同一个数组上写入,并且应用程序因超出范围异常而崩溃。
getPeople
遍历数据的方式是这样的:
-(void)getPeople:(NSDictionary *)peopleDictionary{
//I receive an NSDictionary and I go through it
NSArray *keys = [peopleDictionary allKeys];
int indexOfArray = 0;
for(NSString *key in keys){
//Complex operation that are not important
[peopleInArray insertObjetAtIndex:indexOfArray];//People in array is a global variable
indexOfArray++;
}
}
我无法弄清楚如何摆脱这种情况,我想在第二个队列进入时停止第一个队列,但是GCD没有这个选项...任何其他方式来完成这个,希望没有重大的重新编码,无论如何我现在没有想法,所以任何线索都会有所帮助。
答案 0 :(得分:8)
如果可能的话,我建议您避免与信号量同步。 GCD的设计是为了避免这种情况。后台任务应该准备数据但不要触摸外部状态。准备好数据时,它应该将外部状态的更新分配给一个串行队列,或者,如果状态是绑定到GUI,则分配给主队列。
所以,像这样:
-(void)getPeople:(NSDictionary *)peopleDictionary{
//I receive an NSDictionary and I go through it
NSArray *keys = [peopleDictionary allKeys];
for(NSString *key in keys){
//Complex operation that are not important
dispatch_async(dispatch_get_main_queue(), ^{
[peopleInArray addObject:<whatever>];
});
}
}
如果您想要替换数组,而不是以交错方式添加两个线程,则需要在后台累积整个数组,并将整个peopleInArray
设置为主队列。
如果您想要取消,可以使用旗帜自行实施,或者您应该考虑使用NSOperation
和NSOperationQueue
代替GCD。虽然您的自定义操作仍然需要检查它们是否已被取消并停止工作,但它们具有内置取消的概念。
答案 1 :(得分:2)
你是对的,没有办法阻止派遣的队列。您可以做的一件事是确保只有一个队列同时访问getPeople
semaphores(this might be even more interesting)。
如果您只是想避免用户多次点击该按钮,您可以使用在异步调度中设置为stillExecuting
的bool变量YES
并设置为NO
at getPeople
的结尾。在创建getPeopleQueue
之前,您只需检查getPeople
是否仍在执行。
if(!stillExecuting) {
dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
dispatch_async(getPeopleQueue, ^{
[self getPeople];
});
dispatch_release(getPeopleQueue);
}
答案 2 :(得分:0)
NSString * lastLoginTime = @“您的上次登录时间”;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate* date1 = [dateFormat lastLoginTime];
NSDate* date2 = [dateFormat dateFromString:[NSString currentDateTime]];
NSTimeInterval secondsSinceLastLogin = [date2 timeIntervalSinceDate:date1];
// NSLog(@"Seconds Since Last Login: %g", secondsSinceLastLogin);
int hours = (int)secondsSinceLastLogin / 3600;