在iOS上,你可以发出同步网络请求(在主线程之外)并获得进度回调(在一个单独的非主线程上)吗?
我有一个运行的所有不需要完成耗时作业的串行(一次操作-AT-A-时间)背景排队的权利了.我确实希望显示下载作业的进度.看起来您不能实例化NSURLConnection并配置委托,启动同步连接,然后获取进度回调.
有没有办法在该后台队列上发出同步请求(同步,因为它后面的工作直到完成才开始),并且仍然setProgress:可以发送回调来更新进度条?(回调必须在不同的队列线程上,因为我的串行队列的线程被阻塞,直到请求完成.)
Apple的NSURLConnection文档说,同步请求实际上建立在幕后的异步之上.我必须重新实施吗?我需要一种方法来阻止线程,直到请求完成/失败.到目前为止,我所拥有的最好NSOperationQueue的waitUntilFinished方法是 方法,但我不想在同步方法上启动异步并不断轮询.
NSURLConnection讨论
同步加载构建在类可用的异步加载代码之上.当异步加载系统在专门为此加载请求生成的线程上执行URL加载时,将阻止调用线程.在调用线程中,为了执行同步加载,不需要特殊的线程或运行循环配置.
有人能解释异步NSURL请求与GCD和NSOperationQueues之间的关系吗?
我不确定何时使用它们.
现在,当我需要将数据提取/上传到服务器时,我一直在"逃避"异步NSURL请求.但有人建议我应该使用GCD.我的问题是我不知道现实生活中的例子GCD会更好.有没有人对我有任何常见用例?例如,如果我使用GCD存储10个异步NSURL GET请求的队列,这对我有什么好处?在大型中央调度队列或NSOperationQueue中有异步NSURL请求是否有意义?
谢谢!
nsurlconnection nsoperationqueue grand-central-dispatch ios afnetworking
如果libsqlite不是线程安全的,则类似这样的代码
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block NSArray *__albumsCollection = albumCollections;
dispatch_apply(count, queue, ^(size_t i)
{
MPMediaItem *albumObj = [[__albumsCollection objectAtIndex:i] representativeItem];
///// making some sqlite queries
});
Run Code Online (Sandbox Code Playgroud)
会引发一个BAD_EXEC。
那么如何使此代码线程安全?
我的解决方案是使用主队列
dispatch_apply(count, dispatch_get_main_queue(), ^(size_t i)
{
/// my sqllite queries
});
Run Code Online (Sandbox Code Playgroud)
但我对此不满意。如何使它更好?
有人可以提供一个例子,说明在使用信号量时何时使用DISPATCH_TIME_NOW vs DISPATCH_TIME_FOREVER?
2和我之间的区别是什么?
根据文档,DISPATCH_TIME_NOW表示立即超时.DISPATCH_TIME_FOREVER表示超时无限.
为什么你会想要前者,即:立即超时.
我正在尝试使用GCD一个接一个地放置图像,如下所示
-(void)setUpImages {
NSArray *images = @[[UIImage imageNamed:@"blogger-icon.png"],
[UIImage imageNamed:@"gplus-icon.png"],
[UIImage imageNamed:@"facebok-icon.png"]
];
[images enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
dispatch_sync(dispatch_get_main_queue(), ^{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, idx * ((UIImage*)obj).size.height + idx*30 + 10, ((UIImage*)obj).size.width, ((UIImage*)obj).size.height)];
NSLog(@"index is %@",NSStringFromCGRect(imageView.frame));
[imageView setImage:(UIImage*)obj];
[self.view.layer addSublayer:imageView.layer];
sleep(1);
});
}];
}
Run Code Online (Sandbox Code Playgroud)
我正在使用,dispatch_sync因为我希望它会等到它的块完成(第一个图像放在屏幕上)然后第二个图像将是,所以第三个图像.现在所有的事情都发生在主线上.
但是,似乎我在中间遇到了僵局,我的逻辑在某些方面是错误的.
我需要帮助来了解这种情况.请帮忙.
以下代码中的死锁.为什么?
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
NSLog(@"Hello?");
});
});
Run Code Online (Sandbox Code Playgroud) 我需要将以下Objective-C代码转换为Swift.
static RWBasicCell *sizingCell = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sizingCell = [self.tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
});
Run Code Online (Sandbox Code Playgroud)
我怎么做?我用Google搜索并找到了这个例子.
class SingletonC {
class var sharedInstance : SingletonC {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : SingletonC? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = SingletonC()
}
return Static.instance!
}
}
Run Code Online (Sandbox Code Playgroud)
但这是为了返回一个班级.
我正在尝试使用SWITCH和GCD加载我的数组,以便不停止主线程.但Xcode无法构建我的代码.请任何人解释一下为什么我可以用这种方式使用GCD?
switch (number) {
case 0:
//case 0:exercise_name="??????";
break;
case 1:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self.handsMassage){
/*
NSURL* musicFile = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sound" ofType:@"wav"]];
_click = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:nil];
self.click.delegate = self;
*/
for (int i = 1; i <= 22; i++) {
[self.arrayOfExercise addObject:(id)[UIImage imageNamed:[NSString stringWithFormat:@"ml_%i", i]].CGImage];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.playButton setHidden:NO];
});
});
break;
case 2:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self.loinMassage){
/*
NSURL* musicFile = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sound" ofType:@"wav"]];
_click = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile …Run Code Online (Sandbox Code Playgroud) 我需要能够从Core Data中获取对象并将它们保存在内存中的可变数组中,以避免不断获取和降低UI/UX.问题是我抓住了其他线程上的对象.我也有时在其他线程上写这些对象.因此,我不能只是保存NSManagedObjects在一个数组中,只是调用类似的东西,myManagedObjectContext.performBlock或者myObject.managedObjectContext.PerformBlock因为你不应该在线程之间传递MOC.
我正在考虑使用自定义对象将我需要的数据从CD对象中抛出.这感觉有点愚蠢,因为我已经为实体创建了Model/NSManagedObject类,并且因为自定义对象是可变的,所以它仍然不是线程安全的.这意味着我必须为多个线程上的对象操作执行类似串行队列的操作?因此,例如,每当我想要读/写/删除对象时,我必须将它扔到我的对象serialQueue中.
这一切看起来真的很讨厌所以我想知道这个问题有什么常见的设计模式或类似的东西吗?有没有更好的方法呢?
multithreading core-data grand-central-dispatch nsmanagedobject swift
我一直在使用Swift一段时间,而GCD仍然让我感到困惑.
我读了:
https://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1
以及关于发送的Apple文档:
https://developer.apple.com/documentation/dispatch
我理解GCD允许在不同线程上运行多个任务的整体概念(我认为是正确的).
我不太明白的是Dispatch.main.async"更新UI".
例如,如果我在某处调用api并返回数据 - 比如返回所有数据需要5秒钟,那么如何使用Dispatch.main.async帮助更新UI?如何Dispatch.main.async知道要更新的UI?
而且我仍然不能完全取代GCD,为什么不能在加载所有数据时使用某种观察者或委托或闭包?
如果我正在进行api调用但不立即使用数据,请重新:用GCD"更新UI".只是将数据存储在一个数组中,直到我决定使用它,那么是否需要使用Dispatch.main.async?
我现在一直在使用firebase/firestore作为数据库.Firebase拥有自己的侦听器并以异步方式运行.我仍然无法得到一个很好的答案:在iOS/Swift中处理来自firebase的异步返回的最佳方法.例如,当我的应用程序加载,如果我去firebase获取数据来填充tableviewcontroller,什么是知道所有数据何时返回的最佳方式?我一直在使用代表,但想知道是否以及如何Dispatch.main.async使用.
ios ×6
objective-c ×3
swift ×3
afnetworking ×1
concurrency ×1
core-data ×1
firebase ×1
singleton ×1
sqlite ×1
xcode ×1