How to return from completion handler inside a lazy set var

Multi tool use
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
add a comment |
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
I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try addingreturn
before callingself.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 sayself.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
add a comment |
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
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
ios swift lazy-initialization completionhandler
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 addingreturn
before callingself.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 sayself.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
add a comment |
I think you are forgetting that lazy var's are assigned closures in which you need to return the value of the property. Try addingreturn
before callingself.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 sayself.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
add a comment |
2 Answers
2
active
oldest
votes
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`
}
}
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
add a comment |
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
a very very bad idea since you are essentially blocking the main thread.
– Sulthan
Dec 30 '18 at 8:02
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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`
}
}
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
add a comment |
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`
}
}
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
add a comment |
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`
}
}
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`
}
}
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
add a comment |
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
add a comment |
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
a very very bad idea since you are essentially blocking the main thread.
– Sulthan
Dec 30 '18 at 8:02
add a comment |
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
a very very bad idea since you are essentially blocking the main thread.
– Sulthan
Dec 30 '18 at 8:02
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 callingself.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