> On Apr 25, 2017, at 4:37 PM, Charles Srstka <[email protected]> wrote:
>
>> On Apr 25, 2017, at 9:51 AM, Dave <[email protected]> wrote:
>>
>> Mac Project.
>>
>> Hi All,
>>
>> I’m using performSelector: withObject: afterDelay: in order to postpone
>> further processing until after the current method/run loop as expired, this
>> puts the request at the End of the Queue, my question is, is there anyway of
>> putting it at the head of the Queue so it gets processing before other
>> requests?
>>
>> All the Best
>> Dave
>
> Consider using NSOperationQueue (OperationQueue if you’re using Swift)
> instead of performSelector:withObject:afterDelay:, and have a look at the
> queuePriority property on Operation/NSOperation. The following code:
>
>> import Foundation
>>
>> let op1 = BlockOperation {
>> print("op1")
>> }
>>
>> let op2 = BlockOperation {
>> print("op2")
>> }
>>
>> let quitOp = BlockOperation {
>> exit(0)
>> }
>>
>> quitOp.addDependency(op1)
>> quitOp.addDependency(op2)
>>
>> op1.queuePriority = .veryLow
>> op2.queuePriority = .veryHigh
>>
>> OperationQueue.main.addOperations([op1, op2, quitOp], waitUntilFinished:
>> false)
>>
>> RunLoop.main.run()
>
> outputs:
>
>> op2
>> op1
>
> This shouldn’t be taken as a guarantee, but it does make it more likely that
> your operation will be executed before others.
>
> Charles
Addendum:
After doing some further tests, it appears that the queuePriority property only
affects the ordering relative to other (NS)Operations, and not other things
done by CF/NSRunLoop. I guess I’d had some sort of idealistic vision of the
main run loop submitting its operations to the main operation queue and having
everything work in harmony. In fact, it’s quite the opposite; all operations on
the main queue are performed *after* operations scheduled via CFRunLoop or the
medieval performSelector:etc:etc: methods, so using (NS)OperationQueue will
actually do the opposite of what you want.
From a quick look at the disassembly for __CFRunLoopRun, it appears that
CFRunLoop executes things in the following order: observers, blocks, sources
(performSelector:etc:etc: is implemented using a CFRunLoop source), and
finally, operations on the main dispatch and operation queues. So, unless you
want to kludge together a fake observer and then trigger it, which I would not
recommend, your best bet is probably to use CFRunLoopPerformBlock.
Unfortunately, there’s no way that I can see to prioritize things submitted
this way, so you’ll still run in series with any other operations submitted via
CFRunLoopPerformBlock, but you should run ahead of most everything else. The
test below bears this out:
> import Foundation
>
> let group = DispatchGroup()
>
> class Foo: NSObject {
> @objc func bar() {
> print("something called via performSelector")
> group.leave()
> }
> }
>
> // Do this stuff in an operation after the run loop starts, because it seems
> if the operations are
> // added before the run loop is running, the first one enqueued will run
> first no matter what.
> OperationQueue.main.addOperation {
> let op = BlockOperation {
> print("something called via the main operation queue")
> group.leave()
> }
>
> op.queuePriority = .veryHigh
>
> group.enter()
> OperationQueue.main.addOperation(op)
>
> group.enter()
> DispatchQueue.main.async {
> print("something called via the main dispatch queue")
> group.leave()
> }
>
> group.enter()
> Foo().performSelector(onMainThread: #selector(Foo.bar), with: nil,
> waitUntilDone: false)
>
> let cfRunLoop = RunLoop.main.getCFRunLoop()
>
> group.enter()
> CFRunLoopPerformBlock(cfRunLoop, CFRunLoopMode.commonModes.rawValue) {
> print("Our thingy got called!")
> group.leave()
> }
>
> CFRunLoopWakeUp(cfRunLoop)
>
> group.notify(queue: DispatchQueue.main) {
> exit(0)
> }
> }
>
> RunLoop.main.run()
outputs:
> Our thingy got called!
> something called via performSelector
> something called via the main dispatch queue
> something called via the main operation queue
Unfortunately, I don’t think this is documented anywhere, so there’s no
guarantee it won’t change in future versions of macOS, but for now, it works.
Charles
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]