在尝试取消NSOperationQueue中的请求时,我真的很难过.
重新分配我的"发动机"对象之前,我称之为cancelOperations方法来取消队列中的一切,所以这将包括在飞行ASIHTTPRequests和排队的...如
Engine.m
-(void)getContent {
if (![self queue]) {
[self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
}
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:@selector(requestDone:)];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
}
-(void)requestDone:(ASIHTTPRequest)*request {
// Do something with request
}
-(void)cancelOperations {
[self.queue cancelAllOperations];
[self.queue waitUntilAllOperationsAreFinished];
}
-(void)dealloc {
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
现在,在我的引擎中,我有许多getContent类型的方法,所以我的队列中有不同的请求对象.使用Engine对象时的流程是:
1)打开视图控制器-视图没有负载- alloc和初始化引擎对象
2)//调用各种风格的getContent方法排队一些操作
3)在视图出口,调用[发动机cancelOperations]; 为了(a)停止在飞行中的任何网络的请求,并且还清空队列
4)解除分配图,并且与该发动机:发动机释放];
如果所有的请求都在队列中完成(因为它是空的)这工作得很好,但是如果我cancelOperations同时请求被激活,应用程序崩溃与一个EXC_BAD_ACCESS错误......但毕竟发动机成功地释放......
任何想法为什么会这样?
--EDIT--为错误添加Backtrace:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000b0000000
Crashed Thread: 0 Dispatch …Run Code Online (Sandbox Code Playgroud) 来自文档:
操作对象一次最多只能有一个操作队列,如果操作已经在另一个队列中,则此方法抛出NSInvalidArgumentException异常.同样,如果操作当前正在执行或已经完成执行,则此方法抛出NSInvalidArgumentException异常.
那么如何检查我是否可以安全地将NSOperation添加到队列中?
我知道的唯一方法是添加操作,然后尝试捕获异常,如果操作已经在队列中或之前执行过.
我想测试一个NSOperation子类.我尝试在我的SenTestCase子类中执行此操作:
- (void)setUp {
[super setUp];
_importQueue = [[NSOperationQueue alloc] init];
[_importQueue setMaxConcurrentOperationCount:1];
[_importQueue waitUntilAllOperationsAreFinished];
}
- (void)tearDown {
[_importQueue release];
[super tearDown];
}
- (void)testSomeImport {
ImportOperation *op = [[ImportOperation alloc] initWithFile:...];
[_importQueue addOperation:op];
[op setDelegate:self];
[op release];
}
- (void)opDidFinish:(ImportOperation *)op { // ImportOperation delegate method
// Not getting called
}
Run Code Online (Sandbox Code Playgroud)
但是NSOperation尽管有规定,测试在完成执行之前完成waitUntilAllOperationsAreFinished.
在操作完成之前如何防止测试完成的任何想法?
我正在使用NSOperationQueue,并NSOperation在后台点击时运行一些功能.但是我希望能够在用户点击某个按钮时停止该操作.
我该怎么做?
有点像,[currentoperation stop];
Cancel- 不会对我有用.我想马上停下来.
谢谢
GCD允许根据4个全局优先级队列(高,默认,低,背景)将块调度到队列.我的应用程序中有几个NSOperationQueues但想要以不同的优先级运行每个.据我所知,NSOperationQueue是对GCD的抽象,并且希望为NSOperationQueue设置不同的优先级(类似于GCD优先级队列).有办法吗?(发现可以为操作设置优先级,但不能为队列本身设置优先级).
我正在尝试在特定函数中实现异步URL请求,我希望所有这些请求完成然后执行特定操作但操作先于请求,即在请求完成之前调用它.
dispatch_queue_t fetchQ = dispatch_queue_create("Featured Doc Downloader", NULL);
dispatch_async(fetchQ, ^{
[self myAsyncMultipleURLRequestFunction];
dispatch_sync(dispatch_get_main_queue(), ^{
[self updateUIFunction];
});
});
-(void)myAsyncMultipleURLRequestFunction
{
for (int i=0; i<count; i++)
{
NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
}
Run Code Online (Sandbox Code Playgroud)
现在在myAsyncMultipleURLRequestFunction完成所有请求之前调用updateUIFunction.也尝试使用NSOperaitonQueue,但不能做我真正想要的.
[_operationQ addOperationWithBlock: ^ {
for (int i=0; i<count; i++)
{
NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
}
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
// updating UI
[self updateUIFunction];
}];
}];
Run Code Online (Sandbox Code Playgroud)
我知道这很简单,但我的时间不多了,任何帮助都表示赞赏.
因为NSOperationQueue总是在新线程上运行任务,所以我对运行isConcurrent时的角色感到困惑.NSOperationNSOperationQueue
如果我有两个子类NSOperation,都运行一个异步过程,无论是从推出NSOperationQueue并在这两个我重写isCancelled,isExecuting,isFinished和isReady.如果在一个我覆盖isConcurrent总是return YES和另一个总是如此,将会有什么不同return NO.
谁真的打电话isConcurrent?如何逻辑的变化,如果它是NO或YES.
来自文档:
当isFinished方法返回的值更改为YES时,将执行您提供的完成块.因此,在操作的主要任务完成或取消之后,操作对象执行该块.
我正在使用RestKit/AFNetworking,如果重要的话.
我NSOperation在a中有多个依赖项OperationQueue.我使用完成块来设置我的孩子需要的一些变量(将结果附加到数组).
(task1,...,taskN) - > taskA
taskA addDependency:task1-taskN
taskA是否会收到不完整的数据,因为孩子可以在完成块被触发之前执行?
参考
NSOperations及其completionBlocks同时运行吗?
我通过在完成块中添加一个睡眠进行了简单的测试,结果不一样.完成块在主线程中运行.当所有完成块都处于休眠状态时,子任务就会运行.
objective-c nsoperationqueue objective-c-blocks restkit afnetworking
我正在使用XCTest测试我的代码的一部分,XCTest也在主队列上添加了NSOperations.它看起来像这样:
[NSOperationQueue mainQueue] addOperationAsBlock:^{
// some code happens here
}];
该代码在设备上或在模拟器运行该应用时,但运行单元测试时不运行在所有运行(我不能得到到调试点上块的第一行).
电话:
[NSOperationQueue mainQueue] waitUntilAllOperationsAreFinished];
没有帮助.
有什么建议?我想我缺少一些初始化队列的代码.
*编辑*
感谢您的回答,我添加了我的结果代码以保证完整性:
// add as many operations as you'd like to the mainQueue here
__block BOOL continueCondition = YES;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// this should be the last operation
continueCondition = NO;
}];
while (continueCondition) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} // continue your test here
Run Code Online (Sandbox Code Playgroud)
这工作,因为mainQueue是保证非并发所以这增加将是执行的最后一个最后的操作 - 这样,你甚至不需要更改代码停止测试循环.
参考https://developer.apple.com/reference/foundation/operation,我将Playground设置为 -
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
Run Code Online (Sandbox Code Playgroud)
和控制台日志是 -
op1 working....
op2 working....
op1 finished
op2 finished
Run Code Online (Sandbox Code Playgroud)
我们不应该期望输出是依赖的结果吗? -
op1 working....
op1 finished
op2 working....
op2 finished
Run Code Online (Sandbox Code Playgroud)
与使用相同的结果 - opsQue.addOperations([op1, …
nsoperationqueue ×10
ios ×6
nsoperation ×6
objective-c ×5
iphone ×3
afnetworking ×1
cocoa ×1
macos ×1
restkit ×1
swift ×1
unit-testing ×1
xcode5 ×1
xctest ×1