我正在开发一个创建内容并将其发送到现有后端的应用程序.内容是标题,图片和位置.没有什么花哨.
后端有点复杂,所以这就是我要做的事情:
我已经使用了几个NSOperation子类来完成这项工作,但我并不为我的代码感到自豪,这里有一个示例.
NSOperation *process = [NSBlockOperation blockOperationWithBlock:^{
// Process image before upload
}];
NSOperation *filename = [[NSInvocationOperation alloc] initWithTarget: self selector: @selector(generateFilename) object: nil];
NSOperation *generateEntry = [[NSInvocationOperation alloc] initWithTarget: self selector: @selector(createEntry) object: nil];
NSOperation *uploadImage = [[NSInvocationOperation alloc] initWithTarget: self selector: @selector(uploadImageToCreatedEntry) object: nil];
NSOperation *refresh = [NSBlockOperation blockOperationWithBlock:^{
// Update UI
[SVProgressHUD showSuccessWithStatus: NSLocalizedString(@"Success!", @"Success HUD message")];
}];
[refresh addDependency: uploadImage];
[uploadImage addDependency: generateEntry];
[generateEntry addDependency: filename];
[generateEntry addDependency: process];
[[NSOperationQueue …Run Code Online (Sandbox Code Playgroud) 我有一个NSOperationQueue,它将对象导入Core Data,这是我从web api获得的.每个操作都有我的应用程序的主要managedObjectContext的私有子managedObjectContext.每个操作都会获取要导入的对象,并检查该对象是否已存在,在哪种情况下它会更新现有对象.如果该对象不存在,则创建此新对象.然后,私有子上下文的这些更改将传播到主要托管对象上下文.
这个设置对我来说非常好用,但是有一个重复的问题.
当我在两个不同的并发操作中导入相同的对象时,我得到具有完全相同数据的重复对象.(它们都检查对象是否存在,并且它们看起来不存在).我将在同一时间导入2个相同对象的原因是我经常处理"新"api调用以及"获取"api调用.由于我的设置同时具有异步性质,因此很难确保我不会尝试导入重复的对象.
所以我的问题是解决这个特定问题的最佳方法是什么?我考虑过限制导入到最大并发操作为1(由于性能,我不喜欢这样).类似地,我考虑在每次导入操作之后要求保存并尝试处理上下文的合并.另外,我之后考虑过修饰数据以偶尔清理重复数据.最后,我考虑过只处理所有获取请求的重复项.但是这些解决方案对我来说都不是很好,也许我已经看过一个简单的解决方案了.
multithreading core-data objective-c nsoperation nsmanagedobjectcontext
我有这些方法从互联网上检索一些对象信息:
- (void)downloadAppInfo:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableHosts:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableServices:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableActions:(void(^)())success
failure:(void(^)(NSError *error))failure;
Run Code Online (Sandbox Code Playgroud)
下载的东西存储在对象属性中,这就是成功函数不返回任何内容的原因.
现在,我想要一个像这样的方法:
- (void)syncEverything:(void(^)())success
failure:(void(^)(NSError *error))failure;
Run Code Online (Sandbox Code Playgroud)
除了调用上面的所有方法之外,它只会在每个方法执行其成功或失败块之后返回.
我怎样才能做到这一点?
提示:我知道级联方法调用彼此成功块会起作用.但是,当后来的实现包括更多方法时,这既不"干净"也不有用.
尝试:
我尝试在a中运行每个调用NSOperation并将其添加NSOperations到a NSOperationQueue后跟"完成操作",这取决于前面的每个操作.
这不行.由于即使在各自的成功/失败块返回之前也认为操作已完成.
我也试过用dispatch_group.但我不清楚我是以正确的方式做到这一点.不幸的是,它没有用.
nsoperation nsoperationqueue grand-central-dispatch ios objective-c-blocks
我写了一些异步单元测试,XCTest期望测试我写的网络类.我的大多数测试每次都有效.
当我运行整个套件时,有一些测试会失败,但是会自行传递.
其他测试失败,但使用相同的URL发出请求会在粘贴到浏览器时返回相应的数据.
我的网络代码封装在NSOperation运行的对象上NSOperationQueue.(我的操作队列是默认类型 - 我没有明确地将基础GCD队列设置为串行或并发.)
我可以看一下修复这些测试的内容?在阅读objc.io上的这篇文章后,我假设他们正遭受某种隔离问题.
我对使用NSOperation和绘图有一些建议:
我有一个主线程创建我的NSOperation子类,然后将其添加到NSOperationQueue.
我NSOperation做了一些繁重的处理,它打算在main()方法中循环几分钟,不断处理一些工作,但是现在我只有一个while()循环,里面有一个sleep(1),设置为go大约只有5次(用于测试).
产生它的主(原始)线程NSOperation负责绘制视图并更新UI.
我打算让NSOperation线程使用通知来告诉主线程它已经完成了一些处理,此时每次通过while()循环时都会发送一次这个通知(也就是说,每秒一次,因为它只是在做睡眠(1)).主线程(视图),注册接收这些通知.
通知立即进入主线程,看起来异步,看起来很好.似乎两个线程都按预期运行......即 - 同时运行.(我使用NSLog()来粗略检查每个线程何时发送和接收通知).
当视图收到通知并调用其处理程序方法时,我只是递增一个整数变量,并尝试将其绘制到视图中(当然是一个字符串).在测试中,drawRect中的代码:将此整数(作为字符串)绘制到屏幕上就好了.
但是:这是我的问题(抱歉这需要花一点时间才能到达):当主线程(视图)收到来自NSOperation的通知时,它会更新此测试整数并调用[self setNeedsDisplay].但是,在NSOperation完成之前,视图不会重绘!我期望NSOperation作为一个单独的线程,无法阻止主线程的事件循环,但看起来这就是正在发生的事情.当NSOperation完成并且其main()返回时,视图最终会立即重新绘制.
也许我没有NSOperation正确使用.我在"非并发"模式下使用它,但尽管名称我的理解是这仍然产生一个新线程并允许异步处理.
任何帮助或建议非常感谢,如果您想看到一些代码,请告诉我.
我将一些NSOperation代码转换为ARC时遇到了困难.我的操作对象使用完成块,该完成块又包含一个GCD块,用于更新主线程上的UI.因为我从自己的完成块中引用了我的操作对象,所以我使用__weak指针来避免内存泄漏.但是,在我的代码运行时,指针已经设置为nil.
我把它缩小到这个代码示例.谁知道我哪里出错了,以及正确的方法来实现这一目标?
NSOperationSubclass *operation = [[NSOperationSubclass alloc] init];
__weak NSOperationSubclass *weakOperation = operation;
[operation setCompletionBlock:^{
dispatch_async( dispatch_get_main_queue(), ^{
// fails the check
NSAssert( weakOperation != nil, @"pointer is nil" );
...
});
}];
Run Code Online (Sandbox Code Playgroud) objective-c nsoperation grand-central-dispatch objective-c-blocks automatic-ref-counting
我使用这种AFNetworking方法一次启动多个请求:
- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock
Run Code Online (Sandbox Code Playgroud)
其中一个是AFJSONRequestOperation.问题是此JSON操作的成功块是在批处理的完成块之后执行的.原因是:AFJSONRequestOperation有一个用于JSON处理的内部调度队列.因此,在调用完成块时,JSON数据仍在处理中.
问题:如何在调用JSON操作的成功块之后在完成块中执行代码?
我试图在主队列上调度代码块,但这没有帮助.
我需要知道什么时候NSOperationQueue从队列中删除一个操作?我有NSOperationQueue哪个列表NSOperation.从哪个位置NSOperationQueue删除队列中的操作?
因为在NSOPerationqueue完成所有操作后我需要通知.为此,我提到了 这个链接
我想知道如果仍有一些操作正在运行,那么解除一个ivar NSOperationQueue的正确方法是什么,这通常会在用户突然退出应用程序时发生.在一些例子中,我看到使用了waitUntilAllOperationsAreFinished,如下所示:
- (void)dealloc {
[_queue cancelAllOperations];
[_queue waitUntilAllOperationsAreFinished];
[_queue release];
...
然而,许多人建议避免这样做,因为它会挂起运行循环.那么发布的正确方法是_queue什么?如果我不等待操作完成并继续发布,会发生什么?
是否有相当于[NSOperationQueue currentQueue]或[NSThread currentThread]为NSOperation?
我有一个相当复杂的域模型,其中繁重的处理发生在调用堆栈中.为了及时取消操作,我需要将NSOperation参数作为参数传递给每个方法,直到我想要中断更长时间运行的循环.使用我可以使用的线程,[[NSThread currentThread] isCancelled]如果有一个NSOperation的等价物似乎很方便,不幸的是只有看似无用的东西[NSOperationQueue currentQueue].
nsoperation ×10
ios ×6
objective-c ×4
iphone ×2
afnetworking ×1
cocoa ×1
cocoa-touch ×1
core-data ×1
dealloc ×1
unit-testing ×1
xcode ×1
xctest ×1