哪些任务更适合使用NSOperation,而不是GCD在为iPhone编程时使用?
对我来说,他们似乎做同样的事情.我看不出一方面的优势和劣势.
我正在尝试实现一个操作队列,我有以下场景:
NSOperation A
NSOperation B
NSOperation C
NSOperation D
NSOperationQueue queue
Run Code Online (Sandbox Code Playgroud)
我开始加入A到queue.
在执行期间,A我需要从中获取一些数据B,我无法继续,A直到B返回我需要的内容.
B取决于C和C取决于相同的情况将发生D.
为了管理这个,每个NSOperation我都有这个代码:
NSOperation *operation; //This can be A, B, C, D or any other NSOperation
[self setQueuePriority:NSOperationQueuePriorityVeryLow]; //Set the current NSOperation with low priority
[queue addOperation: operation]; //Add the operation that I want to the queue
while(!operation.isFinished && !self.isCancelled){} //I need to wait the operation that …Run Code Online (Sandbox Code Playgroud) 我有一个必须下载多个大文件的应用程序.我希望它按顺序逐个下载每个文件而不是同时下载.当它同时运行时,应用程序会过载并崩溃.
所以.我试图将downloadTaskWithURL包装在NSBlockOperation中,然后在队列上设置maxConcurrentOperationCount = 1.我在下面编写了这段代码,但由于两个文件同时下载,因此无法正常工作.
import UIKit
class ViewController: UIViewController, NSURLSessionDelegate, NSURLSessionDownloadDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
processURLs()
}
func download(url: NSURL){
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
let downloadTask = session.downloadTaskWithURL(url)
downloadTask.resume()
}
func processURLs(){
//setup queue and set max conncurrent to 1
var queue = NSOperationQueue()
queue.name = "Download queue"
queue.maxConcurrentOperationCount = 1
let url = NSURL(string: "http://azspeastus.blob.core.windows.net/azurespeed/100MB.bin?sv=2014-02-14&sr=b&sig=%2FZNzdvvzwYO%2BQUbrLBQTalz%2F8zByvrUWD%2BDfLmkpZuQ%3D&se=2015-09-01T01%3A48%3A51Z&sp=r") …Run Code Online (Sandbox Code Playgroud) 正如标题所示,NSOperationQueue的maxConcurrentOperationCount的默认值是多少?
是否设置为1的值?
我有两个NSOperation负责下载和解析.下载操作成功后,我收到一些NSData,然后我想将该数据设置为解析操作使用的数据:
init(context: NSManagedObjectContext, completionHandler: Void -> Void) {
downloadOperation = DownloadActivitiesOperation() { data in
self.parseOperation.data = data
}
parseOperation = ParseActivitiesOperation(context: context)
let finishOperation = NSBlockOperation(block: completionHandler)
parseOperation.addDependency(downloadOperation)
finishOperation.addDependency(parseOperation)
super.init(operations: [downloadOperation, parseOperation, finishOperation])
name = "Get Activities"
}
Run Code Online (Sandbox Code Playgroud)
然而,这不起作用,因为我self在调用之前尝试在我的下载完成块中使用super.init.
我的问题是,当尝试将一个操作的结果传递给链中的下一个操作时,最好的方法是什么?
我已阅读并发编程指南
在指南中,文本指出GCD调度队列定义了他们自己的@autoreleasepool池,并提到仍然建议在每个调度级别定义一个,但是对于NSOperation没有说什么,Apple提供的示例代码也没有显示@autoreleasepool结构.在NSOperation的背景下,模糊地提到@autoreleasepool的唯一地方是修订历史,
2012-07-17 - 删除了有关自动释放池使用操作的过时信息.
查看在线提供的示例代码,例如 http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues在基于NSOperations的对象的实现中使用@autoreleasepool,例如:
@implementation ImageDownloader
- (void)main {
@autoreleasepool {
...
}
}
@end
Run Code Online (Sandbox Code Playgroud)
nsoperation nsautoreleasepool ios automatic-ref-counting ios8
我NSOperation在Swift中进行子类化,需要覆盖isExecuting和isFinished属性,因为我重写了start方法.
我遇到的问题是如何保留键值观察(KVO),同时还能够覆盖这些属性.
通常在Obj-C中,这很容易重新声明属性,就像readwrite在类扩展JSONOperation ()定义中一样.但是,我没有在Swift中看到同样的功能.
例:
class JSONOperation : NSOperation, NSURLConnectionDelegate
{
var executing : Bool
{
get { return super.executing }
set { super.executing } // ERROR: readonly in the superclass
}
// Starts the asynchronous NSURLConnection on the main thread
override func start()
{
self.willChangeValueForKey("isExecuting")
self.executing = true
self.didChangeValueForKey("isExecuting")
NSOperationQueue.mainQueue().addOperationWithBlock(
{
self.connection = NSURLConnection(request: self.request, delegate: self, startImmediately: true)
})
}
}
Run Code Online (Sandbox Code Playgroud)
所以这是我提出的解决方案,但它感觉非常丑陋和hacky:
var state = Operation() …Run Code Online (Sandbox Code Playgroud) 我有一个需要将数据(使用POST)发送到服务器的应用程序.此功能必须位于其中一个NavigationController子控制器上,用户应能够远离此控制器和/或关闭应用程序(仅支持iPhone4/iOS4).我应该使用线程/ NSOperations或/并使用现有的异步方法发送数据吗?任何想法/最佳实践如何实现这一点?
iphone multithreading nsoperation grand-central-dispatch ios
使用自定义NSOperation子类时,我注意到[NSOperation automaticallyNotifiesObserversForKey]类方法禁用了自动键值观察(NO至少返回某些键路径).因此,NSOperation子类中的代码通过手动调用来填充,willChangeValueForKey:并且didChange…在Web上的许多代码示例中都可见.
为什么这样NSOperation做?通过自动KVO支持,人们可以简单地声明操作生命周期标志(isExecuting等)的属性,并通过访问器触发KVO事件,即.以下代码:
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
Run Code Online (Sandbox Code Playgroud)
......可以替换为:
[self setIsExecuting:NO];
[self setIsFinished:YES];
Run Code Online (Sandbox Code Playgroud)
在某个地方有捕获吗?我只是覆盖了automaticallyNotifiesObserversForKey返回YES,事情似乎工作正常.
我试图开始Operation在侧面项目中使用s而不是在我的网络代码中散布基于闭包的回调以帮助消除嵌套调用.所以我正在做一些关于这个主题的阅读,我遇到了这个实现:
open class AsynchronousOperation: Operation {
// MARK: - Properties
private let stateQueue = DispatchQueue(label: "asynchronous.operation.state", attributes: .concurrent)
private var rawState = OperationState.ready
private dynamic var state: OperationState {
get {
return stateQueue.sync(execute: {
rawState
})
}
set {
willChangeValue(forKey: "state")
stateQueue.sync(flags: .barrier, execute: {
rawState = newValue
})
didChangeValue(forKey: "state")
}
}
public final override var isReady: Bool {
return state == .ready && super.isReady
}
public final override var isExecuting: Bool {
return state …Run Code Online (Sandbox Code Playgroud) nsoperation ×10
ios ×8
swift ×4
objective-c ×2
cocoa-touch ×1
ios8 ×1
ios9 ×1
iphone ×1
macos ×1
nsthread ×1
nsurlsession ×1