Kodeco Forums

Grand Central Dispatch Tutorial for Swift: Part 1/2

Get started with concurrency and parallelism in part one of this tutorial on Grand Central Dispatch.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/2059-grand-central-dispatch-tutorial-for-swift-part-1-2

I am trying to get this to build and run in Xcode 7.3. I loaded the project and let Xcode do its magic, converting to Swift 
 3? Anyway, I’m seeing the following error in PhotoDetailViewController.swift:

	let features = detector.featuresInImage(newImage) as! [CIFaceFeature]!

“Cannot downcast from ‘[CIFeature]’ to a more optional type ‘[CIFaceFeature]!’”

However, when I remove the ! from [CIFaceFeature], I get a crapton of link errors (91, to be precise), like this:

“Foundation._convertNSArrayToArray (__ObjC.NSArray?) → [A]”, referenced from:
GooglyPuff.PhotoDetailViewController.(faceOverlayImageFromImage in _CB4088193944011D73F91F79417A6871) (__ObjC.UIImage) → __ObjC.UIImage in PhotoDetailViewController.o

What’s going on here? What am I missing?

I’d really like to get this working, as I want to get some in-depth learning going on GCD.

Thanks.

You can try this:

    let features = detector.featuresInImage(newImage)
    ...
    for feature in features {
      guard let faceFeature = feature as? CIFaceFeature else {
        continue
      }

Here is the new way to treat this building bug.
Please let you try to do like this.
// var features = detector.featuresInImage(newImage) as! [CIFaceFeature]!
let features = detector.featuresInImage(newImage, options: [CIDetectorSmile: true]) as! [CIFaceFeature]
I wish this will be helpful.
All the best.

I uploaded an updated version of the project compatible with XCode 7. Here is the link

I got this error while I was trying to build and run this project in Xcode 7.3:

GooglyPuff_Swift_Start_1_Xcode63/GooglyPuff/PhotoCollectionViewController.swift:66:42: Redundant conformance of ‘PhotoCollectionViewController’ to protocol ‘UICollectionViewDataSource’

How can I solve it?

Thanks!

PhotoCollectionViewController inherits from UICollectionViewController, which already implements UICollectionViewDelegate and UICollectionViewDataSource in the latest SDK. Remove the UICollectionViewDelegate and UICollectionViewDataSource parts from the extensions on PhotoCollectionViewController and it should work.

Edit: To clarify, it should read extension PhotoCollectionViewController { ...code... } instead of extension PhotoCollectionViewController: UICollectionViewDataSource { ...code... }.

1 Like

You’re great. It’s working now.

Thanks a lot

I am getting error : Use of undeclared identifier ‘Utils’ in ELCAlbumPickerController class.

my temporary solution: comment it because Utils is just for change background color

// [self.view setBackgroundColor:[Utils defaultBackgroundColor]];
// cell.backgroundColor = [Utils defaultBackgroundColor];

Hi, I have some problem about concurrent queue.

The document says concurrent queue tasks are dequeued in FIFO order, but 


class A  {
    deinit {
        print("A")
    }   
}
class B {
    deinit {
        print("B")
    }
}
class C {
    deinit {
        print("C")
    }
}
class D {
    deinit {
        print("D")
    }
}
let queue  = dispatch_queue_create("Test", DISPATCH_QUEUE_CONCURRENT)
let blockA = {let a = A()}
let blockB = {let b = B()}
let blockC = {let c = C()}
let blockD = {let d = D()}
dispatch_async(queue, blockA)
dispatch_async(queue, blockB)
dispatch_async(queue, blockC)
dispatch_async(queue, blockD)

According to the document says concurrent tasks are dequeued in FIFO order, and I think the result should be:

A
B
C
D

But in fact, the result is:

C
B
D
A

Or the order.

Why?

On a concurrent queue the blocks are dequeued and executed in FIFO order, but that does not mean they finish in the same order. A concurrent queue will have blocks executing at the same time and the order they finish will vary. For instance, if the four blocks are started at the same time but one of them is assigned to a CPU with a heavier load than the others then it will finish later than the other three.

If you need a guaranteed order, use a serial queue. If you need to wait for several dispatched blocks to finish, use dispatch_group. If you have a block that needs to execute non-concurrently on a concurrent queue, use dispatch_barrier (great for multiple-reader single-writer scenarios).

1 Like

Blocks submitted to dispatch queues will look like list:

[blockA, blockB, blockC, blockD]

Even thought the blockB is finished before blockA, but the queue is still maintain the blockB, blockB still maintain the instance of B class.

The blockB is not dequeued until the blockA is dequeued.

Or, how can prove the concurrent tasks are dequeued in FIFO order?

Thanks.

If you do print statements at the start of the blocks you’ll get a better feel for execution order, but it won’t be 100% accurate. Deinit on the objects isn’t necessarily run straight away when execution of the block leaves scope (but I agree, it should), it depends on how ARC handles things. If you want to know exactly how the queue works you can check the libdispatch source at http://libdispatch.macosforge.org.