我是Grand Central Dispatch(GCD)和Core Data的初学者,我需要你的帮助来使用带有CGD的Core Data,这样当我向Core Data添加40.000条记录时,UI不会被锁定.
我知道CD不是线程安全的,所以我必须使用另一个上下文,然后保存数据和合并上下文,就我从一些文章中能够理解的那样.
我还做不到的是把各个部分放在一起.
所以,在我的代码中,我需要你的帮助,如何做到这一点.
我有:
/*some other code*/
for (NSDictionary *memberData in arrayWithResult) {
//get the Activities for this member
NSArray *arrayWithMemberActivities = [activitiesDict objectForKey:[memberData objectForKey:@"MemberID"]];
//create the Member, with the NSSet of Activities
[Members createMemberWithDataFromServer:memberData
andActivitiesArray:arrayWithMemberActivities
andStaffArray:nil
andContactsArray:nil
inManagedObjectContext:self.managedObjectContext];
}
Run Code Online (Sandbox Code Playgroud)
如何将其转换为在后台工作,然后,在完成保存后,保存数据并更新UI,而不会在保存40.000对象时阻止UI?
我使用我的视图控制器将调度队列维护为属性.我在视图控制器的init方法中创建了一次此队列,并重复使用了几次后台任务.在ARC之前,我这样做:
@property (nonatomic, assign) dispatch_queue_t filterMainQueue;
Run Code Online (Sandbox Code Playgroud)
在init中:
if (filterMainQueue == nil) {
filterMainQueue = dispatch_queue_create("com.myQueue.CJFilterMainQueue", NULL);
}
Run Code Online (Sandbox Code Playgroud)
但是在ARC之后,我不确定这应该仍然是"分配",还是应该是"强"还是"弱".ARC转换器脚本没有改变任何东西,但我不确定一个微妙的错误是否来自这个队列在被使用时可能被解除分配的事实?
使用ARC时,3种类型的属性和调度队列最适合的是什么?
最近,我需要一个可用于保证在特定串行调度队列上同步执行给定块的函数.有可能从已经在该队列上运行的东西调用这个共享函数,所以我需要检查这种情况,以防止从同步调度到同一队列的死锁.
我使用如下代码来执行此操作:
void runSynchronouslyOnVideoProcessingQueue(void (^block)(void))
{
dispatch_queue_t videoProcessingQueue = [GPUImageOpenGLESContext sharedOpenGLESQueue];
if (dispatch_get_current_queue() == videoProcessingQueue)
{
block();
}
else
{
dispatch_sync(videoProcessingQueue, block);
}
}
Run Code Online (Sandbox Code Playgroud)
此函数依赖于使用此函数dispatch_get_current_queue()来确定此函数正在运行的队列的标识,并将其与目标队列进行比较.如果匹配,它知道只运行块内联而不调度到该队列,因为该函数已在其上运行.
我听说过是否适当使用dispatch_get_current_queue()这样的比较是有争议的,我在标题中看到了这个措辞:
建议仅用于调试和记录目的:
代码不得对返回的队列做任何假设,除非它是全局队列之一或代码本身创建的队列.如果该队列不是dispatch_get_current_queue()返回的队列,则代码不得假设同步执行到队列是安全的死锁.
此外,在iOS 6.0中(但尚未针对Mountain Lion),GCD标题现在将此功能标记为已弃用.
听起来我不应该以这种方式使用这个功能,但我不确定我应该在它的位置使用什么.对于像上面那样针对主队列的函数,我可以使用[NSThread isMainThread],但是如何检查我是否在我的一个自定义串行队列上运行以便防止死锁?
我正在使用IOS 5中的xmppframework开发一个聊天应用程序; 它完美地运作.但是我将我的xcode更新为4.5.1,将ios5更新为IOS 6,将我的mac OS更新为10.7.5,由于弃用问题,该项目无法正常工作.我用ios 6中的新方法替换了所有方法,除了这一个:
dispatch_get_current_queue()
Run Code Online (Sandbox Code Playgroud)
如何在IOS 6中替换此方法?
我希望能够block在下一个运行循环迭代中执行a .它是否在下一个运行循环的开始或结束时执行并不是那么重要,只是执行被推迟到当前运行循环中的所有代码都已完成执行.
我知道以下内容不起作用,因为它与主运行循环交错,所以我的代码可能会在下一个运行循环中执行,但它可能不会.
dispatch_async(dispatch_get_main_queue(),^{
//my code
});
Run Code Online (Sandbox Code Playgroud)
以下我认为遇到与上述相同的问题:
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void){
//my code
});
Run Code Online (Sandbox Code Playgroud)
现在我相信以下内容可以正常工作,因为它放在当前运行循环的末尾(如果我错了,请纠正我),这实际上有用吗?
[self performSelector:@selector(myMethod) withObject:nil afterDelay:0];
Run Code Online (Sandbox Code Playgroud)
那个有0间隔的计时器怎么样?文档说明:If seconds is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead.这是否可以保证在下一次运行循环迭代中执行?
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(myMethod) userInfo:nil repeats:NO];
Run Code Online (Sandbox Code Playgroud)
这是我能想到的所有选项,但我仍然没有接近于在下一次运行循环迭代中执行一个块(而不是调用方法),并保证它不会更快.
cocoa cocoa-touch objective-c grand-central-dispatch nsrunloop
我正在阅读并发编程指南,事情让我很困惑.
我看到很多代码为任何后台任务调用以下代码:
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Run Code Online (Sandbox Code Playgroud)
现在我所说的'背景'是流行的含义:
在主(UI)线程以外的任何地方执行的操作
因此,遵循文档,上面的语句返回任何具有不同优先级的非主线程队列.
我的问题是 - 为什么会DISPATCH_QUEUE_PRIORITY_BACKGROUND存在?最近我还看到许多异步任务DISPATCH_QUEUE_PRIORITY_BACKGROUND专门用于执行后台任务.
如果返回使用队列DISPATCH_QUEUE_PRIORITY_DEFAULT,是不是返回队列,DISPATCH_QUEUE_PRIORITY_LOW或者DISPATCH_QUEUE_PRIORITY_HIGH远离主线程运行dispatch_get_global_queue?
他们不是背景队列吗?队列返回的具体目的是什么DISPATCH_QUEUE_PRIORITY_BACKGROUND?我已经提到了这一点,但除了我上面提到的流行意义之外,它没有说明多少.
我确信我对语言很困惑 - 背景和背景队列.如果有人可以解释(更好,图形化) - 将是一个很大的帮助.
是否可以将NSUrlConnection包装在gcd样式块中并在low_priority队列上运行?
我需要确保我的连接不在主线程上发生,并且连接需要是异步的.我还需要几个同时发出的请求.
如果我去gcd路由,我不确定调用NSUrlConnectionDelegate方法的哪个线程.
NSURLConnection依赖于委托,所以一旦连接完成,处理它的任何包装类都需要调用它的调用者.我不确定如何处理连接工作启动/完成时调用的所有各种回调:
- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
Run Code Online (Sandbox Code Playgroud)
我应该只调用同步版本但是包含在gcd块中吗?如果我想取消通话,请使用'dispatch_suspend'?
dispatch_async(queue,^{
NSString* result = [self mySynchronousHttp:someURLToInvoke];
});
// If I need to cancel
dispatch_suspend(queue);
Run Code Online (Sandbox Code Playgroud) 我正在使用UIManagedDocument我的项目中使用Core Data 的子类.关键是子类返回一个单例实例,以便我的屏幕可以简单地调用它,并且托管对象上下文对于所有这些实例保持相同.
在使用之前UIManagedDocument,我需要通过打开它来准备它,如果它的文件路径已经存在,或者如果它还没有创建它.我prepareWithCompletionHandler:在子类中创建了一个便捷方法,以方便两种情况.
@implementation SPRManagedDocument
// Singleton class method here. Then...
- (void)prepareWithCompletionHandler:(void (^)(BOOL))completionHandler
{
__block BOOL successful;
// _exists simply checks if the document exists at the given file path.
if (self.exists) {
[self openWithCompletionHandler:^(BOOL success) {
successful = success;
if (success) {
if (self.documentState != UIDocumentStateNormal) {
successful = NO;
}
}
completionHandler(successful);
}];
} else {
[self saveToURL:self.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
successful = success;
if (success) {
if (self.documentState …Run Code Online (Sandbox Code Playgroud) 我正在玩GCD,我写了一个玩具CoinFlipper应用程序.
这是翻转硬币的方法:
- (void)flipCoins:(NSUInteger)nFlips{
// Create the queues for work
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL);
// Split the number of flips into whole chunks of kChunkSize and the remainder.
NSUInteger numberOfWholeChunks = nFlips / kChunkSize;
NSUInteger numberOfRemainingFlips = nFlips - numberOfWholeChunks * kChunkSize;
if (numberOfWholeChunks > 0) {
for (NSUInteger index = 0; index < numberOfWholeChunks; index++) {
dispatch_async(queue, ^{
NSUInteger h = 0;
NSUInteger t = 0;
flipTheCoins(kChunkSize, &h, &t);
dispatch_async(mainQueue, ^{
self.nHeads += h; …Run Code Online (Sandbox Code Playgroud) 当遵守协议或重写超类方法时,您可能无法将方法更改为async,但您可能仍然想调用一些async代码。例如,当我正在重写一个根据 Swift 新的结构化并发编写的程序时,我想async通过class func setUp()覆盖XCTestCase. 我希望我的设置代码在任何测试运行之前完成,因此使用Task.detachedorasync { ... }是不合适的。
最初,我写了一个这样的解决方案:
final class MyTests: XCTestCase {
override class func setUp() {
super.setUp()
unsafeWaitFor {
try! await doSomeSetup()
}
}
}
func unsafeWaitFor(_ f: @escaping () async -> ()) {
let sema = DispatchSemaphore(value: 0)
async {
await f()
sema.signal()
}
sema.wait()
}
Run Code Online (Sandbox Code Playgroud)
这似乎运作良好。然而,在《Swift 并发:幕后花絮》中,运行时工程师 Rokhini Prabhu 指出:
信号量和条件变量等基元与 Swift 并发一起使用是不安全的。这是因为它们隐藏了 Swift 运行时的依赖信息,但在代码的执行中引入了依赖关系……这违反了线程前进的运行时契约。
她还包含了这种不安全代码模式的代码片段
func updateDatabase(_ …Run Code Online (Sandbox Code Playgroud) ios ×5
objective-c ×4
cocoa ×3
iphone ×3
async-await ×1
cocoa-touch ×1
concurrency ×1
core-data ×1
macos ×1
nsrunloop ×1
swift ×1
swift5 ×1