How to return from completion handler inside a lazy set var

Multi tool use
Multi tool use












0















I want to fetch api to get content from server inside lazy var. Following is my code, I'm not sure how to get it working. Any clue? Im aware that we can't return from completion handler so I'm lost here. Not sure what other way to achieve this?



private(set) lazy var orderedViewControllers: [UIViewController] = {
self.fetchPages()
}()

func fetchPages() -> [UIViewController] {
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
var newColoredViewControllerArray: [UIViewController] =
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
// This will not work
return newColoredViewControllerArray
}
} else {
}
}
}
}









share|improve this question























  • I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

    – NSGangster
    Dec 30 '18 at 1:12













  • Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

    – NSGangster
    Dec 30 '18 at 1:16











  • I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

    – Dan
    Dec 30 '18 at 1:21











  • @NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

    – Dan
    Dec 30 '18 at 1:22






  • 1





    the closure cannot contain asynchronous code, it just can't.

    – Sulthan
    Dec 30 '18 at 8:02


















0















I want to fetch api to get content from server inside lazy var. Following is my code, I'm not sure how to get it working. Any clue? Im aware that we can't return from completion handler so I'm lost here. Not sure what other way to achieve this?



private(set) lazy var orderedViewControllers: [UIViewController] = {
self.fetchPages()
}()

func fetchPages() -> [UIViewController] {
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
var newColoredViewControllerArray: [UIViewController] =
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
// This will not work
return newColoredViewControllerArray
}
} else {
}
}
}
}









share|improve this question























  • I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

    – NSGangster
    Dec 30 '18 at 1:12













  • Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

    – NSGangster
    Dec 30 '18 at 1:16











  • I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

    – Dan
    Dec 30 '18 at 1:21











  • @NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

    – Dan
    Dec 30 '18 at 1:22






  • 1





    the closure cannot contain asynchronous code, it just can't.

    – Sulthan
    Dec 30 '18 at 8:02
















0












0








0








I want to fetch api to get content from server inside lazy var. Following is my code, I'm not sure how to get it working. Any clue? Im aware that we can't return from completion handler so I'm lost here. Not sure what other way to achieve this?



private(set) lazy var orderedViewControllers: [UIViewController] = {
self.fetchPages()
}()

func fetchPages() -> [UIViewController] {
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
var newColoredViewControllerArray: [UIViewController] =
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
// This will not work
return newColoredViewControllerArray
}
} else {
}
}
}
}









share|improve this question














I want to fetch api to get content from server inside lazy var. Following is my code, I'm not sure how to get it working. Any clue? Im aware that we can't return from completion handler so I'm lost here. Not sure what other way to achieve this?



private(set) lazy var orderedViewControllers: [UIViewController] = {
self.fetchPages()
}()

func fetchPages() -> [UIViewController] {
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
var newColoredViewControllerArray: [UIViewController] =
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
// This will not work
return newColoredViewControllerArray
}
} else {
}
}
}
}






ios swift lazy-initialization completionhandler






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 30 '18 at 0:49









DanDan

6119




6119













  • I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

    – NSGangster
    Dec 30 '18 at 1:12













  • Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

    – NSGangster
    Dec 30 '18 at 1:16











  • I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

    – Dan
    Dec 30 '18 at 1:21











  • @NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

    – Dan
    Dec 30 '18 at 1:22






  • 1





    the closure cannot contain asynchronous code, it just can't.

    – Sulthan
    Dec 30 '18 at 8:02





















  • I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

    – NSGangster
    Dec 30 '18 at 1:12













  • Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

    – NSGangster
    Dec 30 '18 at 1:16











  • I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

    – Dan
    Dec 30 '18 at 1:21











  • @NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

    – Dan
    Dec 30 '18 at 1:22






  • 1





    the closure cannot contain asynchronous code, it just can't.

    – Sulthan
    Dec 30 '18 at 8:02



















I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

– NSGangster
Dec 30 '18 at 1:12







I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try adding return before calling self.fetchPages() in your lazy var.

– NSGangster
Dec 30 '18 at 1:12















Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

– NSGangster
Dec 30 '18 at 1:16





Also are you sure want a lazy var? Maybe you just need an initially empty array and inside of fetchPages just say self.orderedViewControllers = newColoredViewControllerArray. But I don't know the full context on why you might need a lazy var.

– NSGangster
Dec 30 '18 at 1:16













I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

– Dan
Dec 30 '18 at 1:21





I'm creating these view controllers via lazy var to be used in a page view controller. The content of pages in page view controller will be fetched from API as mentioned in above code.

– Dan
Dec 30 '18 at 1:21













@NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

– Dan
Dec 30 '18 at 1:22





@NSGangster the problem is in fetchPages() function as it will not return, xCode shows error. See this line: // This will not work return newColoredViewControllerArray

– Dan
Dec 30 '18 at 1:22




1




1





the closure cannot contain asynchronous code, it just can't.

– Sulthan
Dec 30 '18 at 8:02







the closure cannot contain asynchronous code, it just can't.

– Sulthan
Dec 30 '18 at 8:02














2 Answers
2






active

oldest

votes


















1














First of all, when you're making async call, don’t return result, use completion handler instead



func fetchPages(_ completion: @escaping ([UIViewController]?) -> ()) {

fetchIntroPages() { result, error in
...
if let result = result {
if result.success {
...
completion(newColoredViewControllerArray)
return
}
}
}
completion(nil)
}

}


then don't use lazy variable because you can’t provide return value since you’re making async call. If you need it, use just "normal" stored variable



var orderedViewControllers: [UIViewController]?


Now where you need it, call fetchPages and in its completion closure assign your variable



fetchPages { viewControllers in
if let viewControllers = viewControllers { // if you don't want to change controllers if there was any error
self.orderedViewControllers = viewControllers
... // moment when you have `orderedViewControllers`
}
}





share|improve this answer


























  • Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

    – Dan
    Dec 30 '18 at 18:48



















-1














You can declare global array of [UIViewcontroller] and use semaphore while completion block



func fetchPages() -> [UIViewController] {
var newColoredViewControllerArray = [UIViewController]()
var semaphore = DispatchSemaphore(value: 0)
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
semaphore.signal()
}
semaphore.wait()
return newColoredViewControllerArray
}


OR
you can return viewcontroller array from using completion



func fetchPages(arrViewController:block) {
var newColoredViewControllerArray = [UIViewController]()
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
arrViewController(newColoredViewControllerArray)

}
}


I hope this is helpfull for you






share|improve this answer


























  • a very very bad idea since you are essentially blocking the main thread.

    – Sulthan
    Dec 30 '18 at 8:02











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53974487%2fhow-to-return-from-completion-handler-inside-a-lazy-set-var%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














First of all, when you're making async call, don’t return result, use completion handler instead



func fetchPages(_ completion: @escaping ([UIViewController]?) -> ()) {

fetchIntroPages() { result, error in
...
if let result = result {
if result.success {
...
completion(newColoredViewControllerArray)
return
}
}
}
completion(nil)
}

}


then don't use lazy variable because you can’t provide return value since you’re making async call. If you need it, use just "normal" stored variable



var orderedViewControllers: [UIViewController]?


Now where you need it, call fetchPages and in its completion closure assign your variable



fetchPages { viewControllers in
if let viewControllers = viewControllers { // if you don't want to change controllers if there was any error
self.orderedViewControllers = viewControllers
... // moment when you have `orderedViewControllers`
}
}





share|improve this answer


























  • Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

    – Dan
    Dec 30 '18 at 18:48
















1














First of all, when you're making async call, don’t return result, use completion handler instead



func fetchPages(_ completion: @escaping ([UIViewController]?) -> ()) {

fetchIntroPages() { result, error in
...
if let result = result {
if result.success {
...
completion(newColoredViewControllerArray)
return
}
}
}
completion(nil)
}

}


then don't use lazy variable because you can’t provide return value since you’re making async call. If you need it, use just "normal" stored variable



var orderedViewControllers: [UIViewController]?


Now where you need it, call fetchPages and in its completion closure assign your variable



fetchPages { viewControllers in
if let viewControllers = viewControllers { // if you don't want to change controllers if there was any error
self.orderedViewControllers = viewControllers
... // moment when you have `orderedViewControllers`
}
}





share|improve this answer


























  • Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

    – Dan
    Dec 30 '18 at 18:48














1












1








1







First of all, when you're making async call, don’t return result, use completion handler instead



func fetchPages(_ completion: @escaping ([UIViewController]?) -> ()) {

fetchIntroPages() { result, error in
...
if let result = result {
if result.success {
...
completion(newColoredViewControllerArray)
return
}
}
}
completion(nil)
}

}


then don't use lazy variable because you can’t provide return value since you’re making async call. If you need it, use just "normal" stored variable



var orderedViewControllers: [UIViewController]?


Now where you need it, call fetchPages and in its completion closure assign your variable



fetchPages { viewControllers in
if let viewControllers = viewControllers { // if you don't want to change controllers if there was any error
self.orderedViewControllers = viewControllers
... // moment when you have `orderedViewControllers`
}
}





share|improve this answer















First of all, when you're making async call, don’t return result, use completion handler instead



func fetchPages(_ completion: @escaping ([UIViewController]?) -> ()) {

fetchIntroPages() { result, error in
...
if let result = result {
if result.success {
...
completion(newColoredViewControllerArray)
return
}
}
}
completion(nil)
}

}


then don't use lazy variable because you can’t provide return value since you’re making async call. If you need it, use just "normal" stored variable



var orderedViewControllers: [UIViewController]?


Now where you need it, call fetchPages and in its completion closure assign your variable



fetchPages { viewControllers in
if let viewControllers = viewControllers { // if you don't want to change controllers if there was any error
self.orderedViewControllers = viewControllers
... // moment when you have `orderedViewControllers`
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 30 '18 at 8:48

























answered Dec 30 '18 at 7:28









Robert DreslerRobert Dresler

5,6701526




5,6701526













  • Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

    – Dan
    Dec 30 '18 at 18:48



















  • Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

    – Dan
    Dec 30 '18 at 18:48

















Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

– Dan
Dec 30 '18 at 18:48





Thanks for solution but this approach will require changing everything in the page controller as the current solution works only with lazy var. I can understand now that returning from completion handler is not possible.

– Dan
Dec 30 '18 at 18:48













-1














You can declare global array of [UIViewcontroller] and use semaphore while completion block



func fetchPages() -> [UIViewController] {
var newColoredViewControllerArray = [UIViewController]()
var semaphore = DispatchSemaphore(value: 0)
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
semaphore.signal()
}
semaphore.wait()
return newColoredViewControllerArray
}


OR
you can return viewcontroller array from using completion



func fetchPages(arrViewController:block) {
var newColoredViewControllerArray = [UIViewController]()
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
arrViewController(newColoredViewControllerArray)

}
}


I hope this is helpfull for you






share|improve this answer


























  • a very very bad idea since you are essentially blocking the main thread.

    – Sulthan
    Dec 30 '18 at 8:02
















-1














You can declare global array of [UIViewcontroller] and use semaphore while completion block



func fetchPages() -> [UIViewController] {
var newColoredViewControllerArray = [UIViewController]()
var semaphore = DispatchSemaphore(value: 0)
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
semaphore.signal()
}
semaphore.wait()
return newColoredViewControllerArray
}


OR
you can return viewcontroller array from using completion



func fetchPages(arrViewController:block) {
var newColoredViewControllerArray = [UIViewController]()
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
arrViewController(newColoredViewControllerArray)

}
}


I hope this is helpfull for you






share|improve this answer


























  • a very very bad idea since you are essentially blocking the main thread.

    – Sulthan
    Dec 30 '18 at 8:02














-1












-1








-1







You can declare global array of [UIViewcontroller] and use semaphore while completion block



func fetchPages() -> [UIViewController] {
var newColoredViewControllerArray = [UIViewController]()
var semaphore = DispatchSemaphore(value: 0)
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
semaphore.signal()
}
semaphore.wait()
return newColoredViewControllerArray
}


OR
you can return viewcontroller array from using completion



func fetchPages(arrViewController:block) {
var newColoredViewControllerArray = [UIViewController]()
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
arrViewController(newColoredViewControllerArray)

}
}


I hope this is helpfull for you






share|improve this answer















You can declare global array of [UIViewcontroller] and use semaphore while completion block



func fetchPages() -> [UIViewController] {
var newColoredViewControllerArray = [UIViewController]()
var semaphore = DispatchSemaphore(value: 0)
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
semaphore.signal()
}
semaphore.wait()
return newColoredViewControllerArray
}


OR
you can return viewcontroller array from using completion



func fetchPages(arrViewController:block) {
var newColoredViewControllerArray = [UIViewController]()
fetchIntroPages() { (result, error) in
if error != nil {
} else {
if result?.data != nil {
if (result?.success)! {
for page in result!.data! {
newColoredViewControllerArray.append(self.newColoredViewController(pageId: page.id!, pageTitle: page.title!, pageContent: page.content!))
}
}
}
}
arrViewController(newColoredViewControllerArray)

}
}


I hope this is helpfull for you







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 1 at 15:52

























answered Dec 30 '18 at 7:03









VijayChaudhayVijayChaudhay

53




53













  • a very very bad idea since you are essentially blocking the main thread.

    – Sulthan
    Dec 30 '18 at 8:02



















  • a very very bad idea since you are essentially blocking the main thread.

    – Sulthan
    Dec 30 '18 at 8:02

















a very very bad idea since you are essentially blocking the main thread.

– Sulthan
Dec 30 '18 at 8:02





a very very bad idea since you are essentially blocking the main thread.

– Sulthan
Dec 30 '18 at 8:02


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53974487%2fhow-to-return-from-completion-handler-inside-a-lazy-set-var%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Je 6jabtGQZgBUlp4sscat A1eQ,TrW1oLeQMcO,8dcOmusEKt
E SSRK7LsC5NcGumoyj,W,d9a3grP81GTkIfXp8mid9

Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas