2016-12-17 3 views
3

С Swift 3 с использованием GCD изменился на DispatchGroup(), и я пытаюсь научиться использовать его в своем коде.Использование DispatchGroup() в Swift 3 для выполнения задачи?

В настоящее время у меня есть функция в другом классе, которая пытается загрузить файл и вывести его скорость. Мне нравится, когда эта функция заканчивается первой, потому что я назначаю ее скорость var, которую я буду использовать в первом классе для выполнения других задач, зависящих от этого var.

Это звучит примерно так:

Второй класс:

func checkSpeed() 
{ 
    // call other functions and perform task to download file from link 

    // print out speed of download 

    nMbps = speedOfDownload 
} 

Первый класс:

let myGroup = DispatchGroup() 
let check: SecondClass = SecondClass() 

myGroup.enter() 

check.checkSpeed() 

myGroup.leave() 

myGroup.notify(queue: DispatchQueue.main, execute: { 

    print("Finished all requests.") 

    print("speed = \(check.nMbps)") 
}) 

Проблема заключается в том Finish all requests получает выход первых, таким образом, возвращая nil для speed, то впоследствии checkSpeed обеспечивает правильную скорость загрузки.

Я считаю, что я делаю это неправильно, но я не уверен?

Как я могу гарантировать, что speed получает правильное значение после завершения checkSpeed в моем первом классе?

Деталь checkSpeed точно так же, как и connectedToNetwork из GitHub: connectedness.swift

+0

Это зависит от того, как ваш 'checkSpeed ​​()' является вызовом задачи загрузки. Вам нужно показать некоторые подробности метода. – OOPer

+1

Если вы говорите о ** одном ** файле, вам нужен асинхронный обработчик завершения, а не группа. – vadian

ответ

2

С намеком, представленным в комментариях и решении, найденные здесь: from @vadian, так как я только выполняю одну задачу, я использовал обработчик завершения асинхронного:

второго класса:

func checkSpeed(completion: @escaping() ->()) 
{ 
    // call other functions and perform task to download file from link 

    // print out speed of download 

    nMbps = speedOfDownload 
    completion() 

} 

Первый класс:

let check: SecondClass = SecondClass() 

check.checkSpeed { 
print("speed = \(check.nMbps)") 

} 

Теперь checkSpeed заполнится первым, а speed присвоено соответствующее значение.

4

После выполнения введенной задачи вам необходимо позвонить DispatchGroup.leave(). Таким образом, в вашем коде myGroup.leave() необходимо разместить в конце обработчика завершения внутри вашего метода checkSpeed().

Вы, возможно, потребуется изменить код так:

func checkSpeed(in myGroup: DispatchGroup) { 
    //... 
    ...downLoadTask... {...its completion handler... in 
     //... 

     // print out speed of download 

     nMbps = speedOfDownload 

     myGroup.leave() //<- This needs to be placed at the end of the completion handler 
    } 
    //You should not place any code after invoking asynchronous task. 
} 

И использовать его как:

myGroup.enter() 

check.checkSpeed(in: myGroup) 

myGroup.notify(queue: DispatchQueue.main, execute: { 

    print("Finished all requests.") 

    print("speed = \(check.nMbps)") 
}) 

Но, как было отмечено в комментарии vadian или ответ Паньгу, вы обычно не используют DispatchGroup для одной асинхронной задачи.


Сложение

Я должен сказать, я настоятельно рекомендую завершающего шаблон обработчика показанного в ответе Паньги в. Это более общий способ обработки асинхронных задач.

Если вы изменили свой checkSpeed() к checkSpeed(completion:) как это было предложено, вы можете легко экспериментировать DispatchGroup так:

let myGroup = DispatchGroup() 
let check: SecondClass = SecondClass() 
let anotherTask: ThirdClass = ThirdClass() 

myGroup.enter() //for `checkSpeed` 
myGroup.enter() //for `doAnotherAsync` 

check.checkSpeed { 
    myGroup.leave() 
} 
anotherTask.doAnotherAsync { 
    myGroup.leave() 
} 

myGroup.notify(queue: DispatchQueue.main) { 

    print("Finished all requests.") 

    print("speed = \(check.nMbps)") 
} 
+0

OOPer: извиниться, что GCD уже смутил меня с самого начала, но, не вдаваясь в подробности, группа 'DispatchGroup' в основном используется для ...? ... групп асинхронных задач? – Pangu

+3

_'DispatchGroup' в основном используется для групп асинхронных задач? _ Право. 'DispatchGroup' предназначен для использования с несколькими асинхронными задачами, чтобы ожидать уведомления, когда ** все ** задачи в группе завершены. Когда все задачи, введенные в группу, вызвали 'DispatchGroup.leave()', вызывается замыкание, указанное с помощью 'notify (queue: execute:)'. – OOPer