सूचना प्राप्त करें जब NSOperationQueue सभी कार्यों को पूरा करता है


92

NSOperationQueueके पास है waitUntilAllOperationsAreFinished, लेकिन मैं इसके लिए समकालिक रूप से इंतजार नहीं करना चाहता। मैं केवल यूआई में प्रगति सूचक को छिपाना चाहता हूं जब कतार समाप्त होती है।

इसे पूरा करने का सबसे अच्छा तरीका क्या है?

मैं अपने NSOperationएस से सूचनाएं नहीं भेज सकता , क्योंकि मुझे नहीं पता कि कौन सा अंतिम होने वाला है, और [queue operations]अधिसूचना प्राप्त होने पर अभी तक खाली नहीं हो सकता है (या बदतर - दोहराव)।


इसे चेक करें अगर आप स्विफ्ट में जीसीडी का उपयोग कर रहे हैं 3. stackoverflow.com/a/44562935/1522584
अभिजीत

जवाबों:


166

operationsअपनी कतार की संपत्ति का निरीक्षण करने के लिए केवीओ का उपयोग करें , फिर आप यह बता सकते हैं कि आपकी कतार की जाँच के द्वारा पूरी हो गई है या नहीं [queue.operations count] == 0

कहीं आप केवीओ में कर रहे फाइल में, केवीओ के लिए एक संदर्भ इस तरह घोषित करें ( अधिक जानकारी ):

static NSString *kQueueOperationsChanged = @"kQueueOperationsChanged";

जब आप अपनी कतार सेटअप करते हैं, तो यह करें:

[self.queue addObserver:self forKeyPath:@"operations" options:0 context:&kQueueOperationsChanged];

फिर अपने में ऐसा करें observeValueForKeyPath:

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                         change:(NSDictionary *)change context:(void *)context
{
    if (object == self.queue && [keyPath isEqualToString:@"operations"] && context == &kQueueOperationsChanged) {
        if ([self.queue.operations count] == 0) {
            // Do something here when your queue has completed
            NSLog(@"queue has completed");
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object 
                               change:change context:context];
    }
}

(यह मानकर चला जाता है कि आपकी NSOperationQueueसंपत्ति नाम की है queue)

आपकी वस्तु से पूरी तरह से निपटने से पहले कुछ बिंदु पर (या जब यह कतार राज्य की देखभाल करना बंद कर देता है), तो आपको केवीओ से इस तरह अपंजीकृत करने की आवश्यकता होगी:

[self.queue removeObserver:self forKeyPath:@"operations" context:&kQueueOperationsChanged];


परिशिष्ट: iOS 4.0 में एक NSOperationQueue.operationCountसंपत्ति है, जो डॉक्स के अनुसार KVO अनुरूप है। यह जवाब अभी भी आईओएस 4.0 में काम करेगा, लेकिन यह अभी भी पीछे की संगतता के लिए उपयोगी है।


26
मेरा तर्क है कि आपको संपत्ति एक्सेसर का उपयोग करना चाहिए, क्योंकि यह भविष्य-प्रूफेड इनकैप्सुलेशन प्रदान करता है (यदि आप तय करते हैं कि उदाहरण के लिए कतार को शुरू करें)। अपने आइवर द्वारा किसी संपत्ति को सीधे एक्सेस करना समय से पहले अनुकूलन माना जा सकता है, लेकिन यह वास्तव में सटीक संदर्भ पर निर्भर करता है। अपने आइवर के माध्यम से एक संपत्ति को सीधे एक्सेस करने से बचाया गया समय आमतौर पर नगण्य होने वाला है, जब तक कि आप उस संपत्ति को 100-1000 गुना एक सेकंड (अविश्वसनीय रूप से क्रूड गाइड के रूप में) से अधिक नहीं बता रहे हैं।
निक फोर्ज

2
केवीओ के उपयोग के कारण खराब होने के लिए उतारा गया। यहां वर्णित उचित उपयोग: dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage
निकोलाई

19
@NikolaiRuhe आप सही हैं - इस कोड का उपयोग करते समय एक वर्ग को उपवर्गित करते हुए जो स्वयं केवीओ का उपयोग करता operationCountहै उसी NSOperationQueueवस्तु पर निरीक्षण करने से संभावित रूप से कीड़े पैदा हो जाएंगे, जिस स्थिति में आपको संदर्भ तर्क का ठीक से उपयोग करने की आवश्यकता होगी। यह होने की संभावना नहीं है, लेकिन निश्चित रूप से संभव है। (स्पार्क + एक लिंक जोड़ने की तुलना में वास्तविक समस्या को वर्तनी में अधिक उपयोगी है)
निक फोर्ज

6
यहां एक दिलचस्प विचार मिला । मैंने NSOperationQueue को उप-वर्ग करने के लिए उपयोग किया, एक NSOperation गुण जोड़ा, 'फाइनलऑपरेशन', जो कतार में जोड़े गए प्रत्येक ऑपरेशन के आश्रित के रूप में सेट किया गया है। जाहिर है AddOperation को ओवरराइड करना था: ऐसा करने के लिए। एक प्रोटोकॉल भी जोड़ा गया है जो अंतिम रूप से पूर्ण होने पर एक प्रतिनिधि को एक संदेश भेजता है। अब तक काम कर रहा है।
pnizzle

1
काफी बेहतर! जब विकल्प निर्दिष्ट किए जाते हैं, तो मैं सबसे अधिक खुश होऊंगा और निष्कासनकर्ता: कॉल को @ प्रयास / @ कैच से लपेटा जाता है - यह आदर्श नहीं है, लेकिन ऐप्पल डॉक्स निर्दिष्ट करते हैं कि रिमूवर को कॉल करते समय कोई सुरक्षा नहीं है: ... if ऑब्जेक्ट में पर्यवेक्षक पंजीकरण नहीं है, जिससे एप्लिकेशन क्रैश हो जाएगा।
ऑस्टिन

20

यदि आप इस व्यवहार से मेल खाने वाली किसी चीज़ की उम्मीद कर रहे हैं (या चाहते हैं):

t=0 add an operation to the queue.  queueucount increments to 1
t=1 add an operation to the queue.  queueucount increments to 2
t=2 add an operation to the queue.  queueucount increments to 3
t=3 operation completes, queuecount decrements to 2
t=4 operation completes, queuecount decrements to 1
t=5 operation completes, queuecount decrements to 0
<your program gets notified that all operations are completed>

आपको इस बात की जानकारी होनी चाहिए कि यदि कई "शॉर्ट" ऑपरेशंस को एक कतार में जोड़ा जा रहा है, तो आप इस व्यवहार को देख सकते हैं (क्योंकि ऑपरेशन्स को कतार में जोड़े जाने के भाग के रूप में शुरू किया गया है):

t=0  add an operation to the queue.  queuecount == 1
t=1  operation completes, queuecount decrements to 0
<your program gets notified that all operations are completed>
t=2  add an operation to the queue.  queuecount == 1
t=3  operation completes, queuecount decrements to 0
<your program gets notified that all operations are completed>
t=4  add an operation to the queue.  queuecount == 1
t=5  operation completes, queuecount decrements to 0
<your program gets notified that all operations are completed>

मेरी परियोजना में मुझे यह जानने की जरूरत थी कि आखिरी ऑपरेशन पूरा होने के बाद, बड़ी संख्या में ऑपरेशन के बाद एक धारावाहिक NSOperationQueue (यानी, maxConcurrentOperationCount = 1) में जोड़ा गया था और केवल जब वे सभी पूरे हो गए थे।

Googling मैं एक प्रश्न के जवाब में एक Apple डेवलपर से यह बयान मिला "एक धारावाहिक NSoperationQueue FIFO है?" -

यदि सभी ऑपरेशनों की प्राथमिकता समान होती है (जो कि एक कतार में जुड़ने के बाद नहीं बदली जाती है) और सभी ऑपरेशन हमेशा होते हैं - isReady == जब तक वे ऑपरेशन कतार में लगाए जाते हैं, तब तक एक धारावाहिक NSOperationQueue FIFO होता है।

क्रिस केन कोको फ्रेमवर्क, एप्पल

मेरे मामले में यह जानना संभव है कि आखिरी ऑपरेशन को कतार में कब जोड़ा गया था। इसलिए अंतिम ऑपरेशन जोड़े जाने के बाद, मैं एक और ऑपरेशन को कतार में जोड़ता हूं, निचली प्राथमिकता का, जो कुछ भी नहीं करता है, लेकिन अधिसूचना को भेजें कि कतार खाली कर दी गई थी। एप्पल के बयान को देखते हुए, यह सुनिश्चित करता है कि सभी कार्यों के पूरा होने के बाद केवल एक ही नोटिस भेजा जाता है।

यदि संचालन को ऐसे तरीके से जोड़ा जा रहा है, जो पिछले एक (यानी, गैर-नियतात्मक) का पता लगाने की अनुमति नहीं देता है, तो मुझे लगता है कि आपको ऊपर उल्लिखित KVO दृष्टिकोण के साथ जाना होगा, अतिरिक्त गार्ड तर्क के साथ अगर यह पता लगाने की कोशिश की गयी तो संचालन जोड़ा जा सकता है।

:)


नमस्ते, क्या आप जानते हैं कि क्या और कैसे संभव हो सकता है जब अधिकतमऑनकोर्सऑपरेशनकाउंट = 1 के साथ NSOperationQueue का उपयोग करके कतार में प्रत्येक ऑपरेशन समाप्त हो जाता है?
सेफ्रान 2

@fran: मैं संचालन पूरा होने पर एक अधिसूचना पोस्ट करेंगे। इस तरह से अन्य मॉड्यूल पर्यवेक्षकों के रूप में पंजीकृत हो सकते हैं, और प्रत्येक पूर्ण के रूप में प्रतिक्रिया दे सकते हैं। यदि आपका @selector एक अधिसूचना ऑब्जेक्ट लेता है, तो आप आसानी से उस ऑब्जेक्ट को पुनः प्राप्त कर सकते हैं, जिसने अधिसूचना को पोस्ट किया है, यदि आपको पूरा होने के बारे में अधिक जानकारी चाहिए।
सॉफ्टवेयर का विकास

17

एक NSOperation जोड़ने के बारे में कैसे जो अन्य सभी पर निर्भर है इसलिए यह अंतिम चलेगा?


1
यह काम कर सकता है, लेकिन यह एक हैवीवेट समाधान है, और यदि आपको कतार में नए कार्यों को जोड़ने की आवश्यकता है, तो इसे प्रबंधित करने में दर्द होगा।
कोर्नेल

यह वास्तव में बहुत ही सुंदर है और जिसे मैंने सबसे ज्यादा पसंद किया है! आपको मेरा वोट
यारिव निसिम

1
व्यक्तिगत रूप से यह मेरा पसंदीदा समाधान है। आप आसानी से पूरा होने वाले ब्लॉक के लिए एक सरल NSBlockOperation बना सकते हैं जो अन्य सभी कार्यों पर निर्भर करता है।
पुनीत सेठी

आप उस समस्या को हिट कर सकते हैं जब पंक्ति रद्द होने पर NSBlockOperation को कॉल नहीं किया जाता है। तो आपको अपना खुद का ऑपरेशन करना होगा जो रद्द होने पर एक त्रुटि बनाता है और एक त्रुटि पैराम के साथ एक ब्लॉक को कॉल करता है।
मल्हल

यह सबसे अच्छा जवाब है!
ट्रैपर

12

एक विकल्प जीसीडी का उपयोग करना है। का संदर्भ लें इस संदर्भ के रूप में।

dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group,queue,^{
 NSLog(@"Block 1");
 //run first NSOperation here
});

dispatch_group_async(group,queue,^{
 NSLog(@"Block 2");
 //run second NSOperation here
});

//or from for loop
for (NSOperation *operation in operations)
{
   dispatch_group_async(group,queue,^{
      [operation start];
   });
}

dispatch_group_notify(group,queue,^{
 NSLog(@"Final block");
 //hide progress indicator here
});

5

यह मेरा इसे करने का तरीका है।

कतार को सेट करें, और संचालन गुण में परिवर्तन के लिए पंजीकरण करें:

myQueue = [[NSOperationQueue alloc] init];
[myQueue addObserver: self forKeyPath: @"operations" options: NSKeyValueObservingOptionNew context: NULL];

... और प्रेक्षक (इस मामले में self)

- (void) observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context {

    if (
        object == myQueue
        &&
        [@"operations" isEqual: keyPath]
    ) {

        NSArray *operations = [change objectForKey:NSKeyValueChangeNewKey];

        if ( [self hasActiveOperations: operations] ) {
            [spinner startAnimating];
        } else {
            [spinner stopAnimating];
        }
    }
}

- (BOOL) hasActiveOperations:(NSArray *) operations {
    for ( id operation in operations ) {
        if ( [operation isExecuting] && ! [operation isCancelled] ) {
            return YES;
        }
    }

    return NO;
}

इस उदाहरण में "स्पिनर" एक UIActivityIndicatorViewदिखावा है कि कुछ हो रहा है। जाहिर है आप सूट को बदल सकते हैं ...


2
यह forलूप संभावित रूप से महंगा लगता है (यदि आप एक ही बार में सभी कार्यों को रद्द कर देते हैं? क्या कतार को साफ करने पर द्विघात प्रदर्शन नहीं होगा?)
कोर्नेल

एक अच्छा है, लेकिन थ्रेड्स के साथ सावधान रहें, क्योंकि, प्रलेखन के अनुसार: "... एक ऑपरेशन कतार से जुड़ी केवीओ सूचनाएं किसी भी धागे में हो सकती हैं।" शायद, आपको स्पिनर को अपडेट करने से पहले निष्पादन प्रवाह को मुख्य ऑपरेशन कतार में ले जाना होगा
इगोर वासीलेव

3

मैं ऐसा करने के लिए एक श्रेणी का उपयोग कर रहा हूं।

NSOperationQueue + Completion.h

//
//  NSOperationQueue+Completion.h
//  QueueTest
//
//  Created by Artem Stepanenko on 23.11.13.
//  Copyright (c) 2013 Artem Stepanenko. All rights reserved.
//

typedef void (^NSOperationQueueCompletion) (void);

@interface NSOperationQueue (Completion)

/**
 * Remarks:
 *
 * 1. Invokes completion handler just a single time when previously added operations are finished.
 * 2. Completion handler is called in a main thread.
 */

- (void)setCompletion:(NSOperationQueueCompletion)completion;

@end

NSOperationQueue + Completion.m

//
//  NSOperationQueue+Completion.m
//  QueueTest
//
//  Created by Artem Stepanenko on 23.11.13.
//  Copyright (c) 2013 Artem Stepanenko. All rights reserved.
//

#import "NSOperationQueue+Completion.h"

@implementation NSOperationQueue (Completion)

- (void)setCompletion:(NSOperationQueueCompletion)completion
{
    NSOperationQueueCompletion copiedCompletion = [completion copy];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self waitUntilAllOperationsAreFinished];

        dispatch_async(dispatch_get_main_queue(), ^{
            copiedCompletion();
        });
    });
}

@end

उपयोग :

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    // ...
}];

NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    // ...
}];

[operation2 addDependency:operation1];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation1, operation2] waitUntilFinished:YES];

[queue setCompletion:^{
    // handle operation queue's completion here (launched in main thread!)
}];

स्रोत: https://gist.github.com/artemstepanenko/7620471


यह क्यों पूरा हो रहा है ? एक NSOperationQueue पूरा नहीं होता है - यह केवल खाली हो जाता है। NSOperationQueue के जीवनकाल के दौरान कई बार खाली स्थिति में प्रवेश किया जा सकता है।
काउचड्यूपर

यह काम नहीं करता है अगर op1 और op2 खत्म करने से पहले setCompletion कहा जाता है।
मल्हल

उत्कृष्ट जवाब, सिर्फ 1 कैविएट जिसे पूरा करने वाला ब्लॉक कहा जाता है जब कतार सभी ऑपरेशन शुरू करने के साथ होती है। परिचालन शुरू करना! = संचालन पूरा होना।
साकिब सऊद

हम्म पुराना जवाब, लेकिन मैं शर्त लगा waitUntilFinishedसकता YES
हूं

3

के रूप में आईओएस 13.0 , operationCount और आपरेशन गुण पदावनत कर रहे हैं। यह केवल उतना ही सरल है जितना कि आप अपनी कतार में परिचालनों की संख्या पर नज़र रखते हैं और जब वे सभी पूर्ण हो जाते हैं तो एक सूचना को बंद कर देते हैं। यह उदाहरण ऑपरेशन के एक अतुल्यकालिक उपवर्ग के साथ भी काम करता है।

class MyOperationQueue: OperationQueue {
            
    public var numberOfOperations: Int = 0 {
        didSet {
            if numberOfOperations == 0 {
                print("All operations completed.")
                
                NotificationCenter.default.post(name: .init("OperationsCompleted"), object: nil)
            }
        }
    }
    
    public var isEmpty: Bool {
        return numberOfOperations == 0
    }
    
    override func addOperation(_ op: Operation) {
        super.addOperation(op)
        
        numberOfOperations += 1
    }
    
    override func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool) {
        super.addOperations(ops, waitUntilFinished: wait)
        
        numberOfOperations += ops.count
    }
    
    public func decrementOperationCount() {
        numberOfOperations -= 1
    }
}

नीचे आसान अतुल्यकालिक संचालन के लिए ऑपरेशन का एक उपवर्ग है

class AsyncOperation: Operation {
    
    let queue: MyOperationQueue

enum State: String {
    case Ready, Executing, Finished
    
    fileprivate var keyPath: String {
        return "is" + rawValue
    }
}

var state = State.Ready {
    willSet {
        willChangeValue(forKey: newValue.keyPath)
        willChangeValue(forKey: state.keyPath)
    }
    
    didSet {
        didChangeValue(forKey: oldValue.keyPath)
        didChangeValue(forKey: state.keyPath)
        
        if state == .Finished {
            queue.decrementOperationCount()
        }
    }
}

override var isReady: Bool {
    return super.isReady && state == .Ready
}

override var isExecuting: Bool {
    return state == .Executing
}

override var isFinished: Bool {
    return state == .Finished
}

override var isAsynchronous: Bool {
    return true
}

public init(queue: MyOperationQueue) {
    self.queue = queue
    super.init()
}

override func start() {
    if isCancelled {
        state = .Finished
        return
    }
    
    main()
    state = .Executing
}

override func cancel() {
    state = .Finished
}

override func main() {
    fatalError("Subclasses must override main without calling super.")
}

}


decrementOperationCount()विधि कहाँ से मंगाई जाती है?
.सनाई

@iksnae - मैंने ऑपरेशन के एक उपवर्ग के साथ अपना उत्तर अपडेट किया है । मैं अपने राज्य चर के डिसेट के भीतर decrementOperationCount () का उपयोग करता हूं । उम्मीद है की यह मदद करेगा!
कालेब लिंडसे

2

operationCountकतार की संपत्ति का निरीक्षण करने के लिए KVO का उपयोग करने के बारे में क्या ? तब आप इसके बारे में सुनेंगे जब कतार खाली हो गई, और जब यह खाली होना बंद हो गया। प्रगति सूचक के साथ व्यवहार करना उतना ही सरल हो सकता है जितना कि कुछ करना:

[indicator setHidden:([queue operationCount]==0)]

क्या यह आपके लिए काम करता है? मेरे आवेदन में NSOperationQueue3.1 से शिकायत है कि यह कुंजी के लिए केवीओ-अनुपालन नहीं है operationCount
जूल १

मैं वास्तव में एक अनुप्रयोग में इस समाधान की कोशिश नहीं की, नहीं। ओपी ने किया या नहीं। लेकिन प्रलेखन स्पष्ट रूप से कहता है कि यह काम करना चाहिए । मैं एक बग रिपोर्ट दर्ज करूंगा। developer.apple.com/iphone/library/documentation/Cocoa/...
Sixten ओटो

IPhone SDK में NSOperationQueue पर कोई ऑपरेशनकाउंट प्रॉपर्टी नहीं है (कम से कम 3.1.3 के रूप में नहीं)। आप अधिकतम OS X प्रलेखन पृष्ठ ( डेवलपर.
apple.com/Mac/library/documentation/Cocoa/Reference/…

1
समय सभी घावों को भर देता है ... और कभी-कभी गलत उत्तर। IOS 4 के रूप में, operationCountसंपत्ति मौजूद है।
सिक्सटेन ओटो

2

अंतिम ऑपरेशन जोड़ें जैसे:

NSInvocationOperation *callbackOperation = [[NSInvocationOperation alloc] initWithTarget:object selector:selector object:nil];

इसलिए:

- (void)method:(id)object withSelector:(SEL)selector{
     NSInvocationOperation *callbackOperation = [[NSInvocationOperation alloc] initWithTarget:object selector:selector object:nil];
     [callbackOperation addDependency: ...];
     [operationQueue addOperation:callbackOperation]; 

}

3
जब कार्यों को समवर्ती रूप से निष्पादित किया जाता है तो यह गलत दृष्टिकोण है।
मार्सिन

2
और जब कतार रद्द हो जाती है तो यह अंतिम ऑपरेशन भी शुरू नहीं होता है।
मल्हल

2

ReactiveObjC के साथ मुझे यह अच्छी तरह से काम करता है:

// skip 1 time here to ignore the very first call which occurs upon initialization of the RAC block
[[RACObserve(self.operationQueue, operationCount) skip:1] subscribeNext:^(NSNumber *operationCount) {
    if ([operationCount integerValue] == 0) {
         // operations are done processing
         NSLog(@"Finished!");
    }
}];

1

FYI करें, आप GCD साथ इस लक्ष्य को हासिल कर सकते हैं dispatch_group में तेजी से 3 । सभी कार्य समाप्त होने पर आपको सूचित किया जा सकता है।

let group = DispatchGroup()

    group.enter()
    run(after: 6) {
      print(" 6 seconds")
      group.leave()
    }

    group.enter()
    run(after: 4) {
      print(" 4 seconds")
      group.leave()
    }

    group.enter()
    run(after: 2) {
      print(" 2 seconds")
      group.leave()
    }

    group.enter()
    run(after: 1) {
      print(" 1 second")
      group.leave()
    }


    group.notify(queue: DispatchQueue.global(qos: .background)) {
      print("All async calls completed")
}

इसका उपयोग करने के लिए न्यूनतम iOS संस्करण क्या है?
नितेश बोरड़

यह स्विफ्ट 3, आईओएस 8 या उच्चतर से उपलब्ध है।
अभिजीत

0

आप एक नया बना सकते हैं NSThread, या पृष्ठभूमि में एक चयनकर्ता को निष्पादित कर सकते हैं , और वहां प्रतीक्षा कर सकते हैं। जब NSOperationQueueखत्म हो जाए, तो आप अपनी खुद की एक सूचना भेज सकते हैं।

मैं कुछ इस तरह सोच रहा हूँ:

- (void)someMethod {
    // Queue everything in your operationQueue (instance variable)
    [self performSelectorInBackground:@selector(waitForQueue)];
    // Continue as usual
}

...

- (void)waitForQueue {
    [operationQueue waitUntilAllOperationsAreFinished];
    [[NSNotificationCenter defaultCenter] postNotification:@"queueFinished"];
}

यह सिर्फ सोने के लिए डाल करने के लिए धागा बनाने के लिए थोड़ा मूर्खतापूर्ण लगता है।
कोर्नेल

मैं सहमत हूँ। फिर भी, मुझे इसके आसपास कोई दूसरा रास्ता नहीं मिला।
पग

आप यह कैसे सुनिश्चित करेंगे कि केवल एक धागा प्रतीक्षा कर रहा है? मैंने झंडे के बारे में सोचा, लेकिन उसे दौड़ की स्थितियों से बचाने की आवश्यकता है, और मैंने अपने स्वाद के लिए बहुत अधिक NSLock का उपयोग किया है।
कोर्नेल

मुझे लगता है कि आप NSOperationQueue को किसी अन्य ऑब्जेक्ट में लपेट सकते हैं। जब भी आप एक NSOperation को कतार में रखते हैं, तो आप एक संख्या बढ़ाते हैं और एक थ्रेड लॉन्च करते हैं। जब भी कोई थ्रेड समाप्त होता है तो आप उस संख्या को एक से घटा देते हैं। मैं एक ऐसे परिदृश्य पर सोच रहा था जहां आप पहले से सब कुछ कतार में लगा सकते हैं, और फिर कतार शुरू कर सकते हैं, इसलिए आपको केवल एक प्रतीक्षा धागा की आवश्यकता होगी।
पग

0

यदि आप इस ऑपरेशन को अपने बेस क्लास के रूप में उपयोग करते हैं, तो आप ऑपरेशनwhenEmpty {} क्यू को ब्लॉक कर सकते हैं :

let queue = OOperationQueue()
queue.addOperation(op)
queue.addOperation(delayOp)

queue.addExecution { finished in
    delay(0.5) { finished() }
}

queue.whenEmpty = {
    print("all operations finished")
}

1
मूल्य के प्रकार 'ऑपरेशनक्यूएयू' का कोई सदस्य नहीं है जब 'खाली'
डेल

@ यदि आप लिंक पर क्लिक करते हैं, तो यह आपको एक जीथब पृष्ठ पर ले जाएगा जहां सब कुछ समझाया गया है। यदि मैं सही ढंग से याद करता हूं, तो उत्तर तब लिखा गया था जब फाउंडेशन के ऑपरेशन क्यू को अभी भी NSOperationQueue कहा जाता था; इसलिए शायद कम अस्पष्टता थी।
user1244109

मेरा बुरा ... मैंने गलत निष्कर्ष निकाला कि ऊपर "ऑपरेशन क्यू" स्विफ्ट 4 के "ऑपरेशनक्यूयू" था।
डेल

0

केवीओ के बिना

private let queue = OperationQueue()

private func addOperations(_ operations: [Operation], completionHandler: @escaping () -> ()) {
    DispatchQueue.global().async { [unowned self] in
        self.queue.addOperations(operations, waitUntilFinished: true)
        DispatchQueue.main.async(execute: completionHandler)
    }
}

0

यदि आप यहाँ गठबंधन के साथ एक समाधान की तलाश में हैं - मैं अपनी खुद की राज्य वस्तु सुनने के लिए समाप्त हो गया।

@Published var state: OperationState = .ready
var sub: Any?

sub = self.$state.sink(receiveValue: { (state) in
 print("state updated: \(state)")
})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.