How to wait for initialization to complete before returning a singleton instance in SwiftHow to call Objective-C code from SwiftUsing a dispatch_once singleton model in SwiftSwift Beta performance: sorting arraysHow to call a class method in a convenience initializer in SwiftDoes Swift execute the methods of a class as part of initializing it?Wait until Boolean is True in Swift?In Swift, What is the difference between a Singleton and the static version of a class?How to wait for Function to finish before continuingiOS will CATransaction wait after viewDidDisappear before calling the completion blockThread safety of method calls on “shared” static constant property
Why do we use caret (^) as the symbol for ctrl/control?
Are there any Final Fantasy Spirits in Super Smash Bros Ultimate?
What is the name of this hexagon/pentagon polyhedron?
Manager is threatening to grade me poorly if I don't complete the project
What is the difference between 'unconcealed' and 'revealed'?
How might a mountain bowl form?
Point of the the Dothraki's attack in GoT S8E3?
Is there something "wrong" with my writing? How do I improve it?
Is it possible to know which is the correct temperature range and speed for any model?
What property of a BJT transistor makes it an amplifier?
Reducing the white spacing
Why is "Vayechulu" said 3 times on Leil Shabbat?
Can there be a single technologically advanced nation, in a continent full of non-technologically advanced nations?
SQLServerLogMgr::LogWriter: Operating system error 1117
Is this homebrew life-stealing melee cantrip unbalanced?
How to calculate the node voltages for this circuit using the voltage divider rule
What does a spell range of "25 ft. + 5 ft./2 levels" mean?
How do LIGO and VIRGO know that a gravitational wave has its origin in a neutron star or a black hole?
Timing of New Changes in Change Sets
Have I damaged my car by attempting to reverse with hand/park brake up?
Why Isn’t SQL More Refactorable?
What matters more when it comes to book covers? Is it ‘professional quality’ or relevancy?
Distribution normality check
Did we get closer to another plane than we were supposed to, or was the pilot just protecting our delicate sensibilities?
How to wait for initialization to complete before returning a singleton instance in Swift
How to call Objective-C code from SwiftUsing a dispatch_once singleton model in SwiftSwift Beta performance: sorting arraysHow to call a class method in a convenience initializer in SwiftDoes Swift execute the methods of a class as part of initializing it?Wait until Boolean is True in Swift?In Swift, What is the difference between a Singleton and the static version of a class?How to wait for Function to finish before continuingiOS will CATransaction wait after viewDidDisappear before calling the completion blockThread safety of method calls on “shared” static constant property
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have a singleton class, which requires a network operation with asynchronous callback to initialize. Any member function of that class should only be called when initialization callback finished.
What I'm not clear with, is how to wait for asynch callback to finish before I return a singleton instance to a caller? Or maybe is there any other way to ensure initialization completes before any function can be called (only initialization should be sequential, all operations after that shouldn't be).
Here's the minimal code:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
public func doSomething()
// this function should only run after asynch callback was executed
This class is called by other classes and potentially other threads like this:
DataProvider.instance.doSomething()
swift
|
show 2 more comments
I have a singleton class, which requires a network operation with asynchronous callback to initialize. Any member function of that class should only be called when initialization callback finished.
What I'm not clear with, is how to wait for asynch callback to finish before I return a singleton instance to a caller? Or maybe is there any other way to ensure initialization completes before any function can be called (only initialization should be sequential, all operations after that shouldn't be).
Here's the minimal code:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
public func doSomething()
// this function should only run after asynch callback was executed
This class is called by other classes and potentially other threads like this:
DataProvider.instance.doSomething()
swift
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
The simplest solution would be to pass a closure as a parameter todoSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls todoSomethingimmediately
– Augusto Dias Noronha
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16
|
show 2 more comments
I have a singleton class, which requires a network operation with asynchronous callback to initialize. Any member function of that class should only be called when initialization callback finished.
What I'm not clear with, is how to wait for asynch callback to finish before I return a singleton instance to a caller? Or maybe is there any other way to ensure initialization completes before any function can be called (only initialization should be sequential, all operations after that shouldn't be).
Here's the minimal code:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
public func doSomething()
// this function should only run after asynch callback was executed
This class is called by other classes and potentially other threads like this:
DataProvider.instance.doSomething()
swift
I have a singleton class, which requires a network operation with asynchronous callback to initialize. Any member function of that class should only be called when initialization callback finished.
What I'm not clear with, is how to wait for asynch callback to finish before I return a singleton instance to a caller? Or maybe is there any other way to ensure initialization completes before any function can be called (only initialization should be sequential, all operations after that shouldn't be).
Here's the minimal code:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
public func doSomething()
// this function should only run after asynch callback was executed
This class is called by other classes and potentially other threads like this:
DataProvider.instance.doSomething()
swift
swift
asked Mar 22 at 21:54
Kiril S.Kiril S.
5,81652245
5,81652245
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
The simplest solution would be to pass a closure as a parameter todoSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls todoSomethingimmediately
– Augusto Dias Noronha
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16
|
show 2 more comments
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
The simplest solution would be to pass a closure as a parameter todoSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls todoSomethingimmediately
– Augusto Dias Noronha
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
The simplest solution would be to pass a closure as a parameter to
doSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls to doSomething immediately– Augusto Dias Noronha
Mar 22 at 22:00
The simplest solution would be to pass a closure as a parameter to
doSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls to doSomething immediately– Augusto Dias Noronha
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16
|
show 2 more comments
1 Answer
1
active
oldest
votes
With some help, I found a good solution, that is both reliable and simple. The solution is to use count-down latch. Unfortunately there's no built-in class like that in Swift, but some implementations could be found online (for example: this class from Uber). So this is a solution:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private let initLatch = CountDownLatch(1)
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
initLatch.countDown()
public func doSomething()
initLatch.await()
// this function should only run after asynch callback was executed
So what does it do:
- the latch is set to 1 so any caller of
doSomethingwill be suspended until latch is decremented to 0 - latch is only decremented to 0 in one place (init completion callback), hence nobody will proceed before initialization completed
- but after latch is set to 0, calling
doSomethingwill not be delayed
Notes:
- This is a simplified model for problem and solution. In reality there are some other factors that may need to be taken into account, and would require other concurrency tools.
- In my case, the callers are non-interactive, hence I do want them to wait rather than be asynchronous. If callers were interactive, I'd let them deal with asynchronous nature of this class instead.
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
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%2f55308276%2fhow-to-wait-for-initialization-to-complete-before-returning-a-singleton-instance%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
With some help, I found a good solution, that is both reliable and simple. The solution is to use count-down latch. Unfortunately there's no built-in class like that in Swift, but some implementations could be found online (for example: this class from Uber). So this is a solution:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private let initLatch = CountDownLatch(1)
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
initLatch.countDown()
public func doSomething()
initLatch.await()
// this function should only run after asynch callback was executed
So what does it do:
- the latch is set to 1 so any caller of
doSomethingwill be suspended until latch is decremented to 0 - latch is only decremented to 0 in one place (init completion callback), hence nobody will proceed before initialization completed
- but after latch is set to 0, calling
doSomethingwill not be delayed
Notes:
- This is a simplified model for problem and solution. In reality there are some other factors that may need to be taken into account, and would require other concurrency tools.
- In my case, the callers are non-interactive, hence I do want them to wait rather than be asynchronous. If callers were interactive, I'd let them deal with asynchronous nature of this class instead.
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
add a comment |
With some help, I found a good solution, that is both reliable and simple. The solution is to use count-down latch. Unfortunately there's no built-in class like that in Swift, but some implementations could be found online (for example: this class from Uber). So this is a solution:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private let initLatch = CountDownLatch(1)
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
initLatch.countDown()
public func doSomething()
initLatch.await()
// this function should only run after asynch callback was executed
So what does it do:
- the latch is set to 1 so any caller of
doSomethingwill be suspended until latch is decremented to 0 - latch is only decremented to 0 in one place (init completion callback), hence nobody will proceed before initialization completed
- but after latch is set to 0, calling
doSomethingwill not be delayed
Notes:
- This is a simplified model for problem and solution. In reality there are some other factors that may need to be taken into account, and would require other concurrency tools.
- In my case, the callers are non-interactive, hence I do want them to wait rather than be asynchronous. If callers were interactive, I'd let them deal with asynchronous nature of this class instead.
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
add a comment |
With some help, I found a good solution, that is both reliable and simple. The solution is to use count-down latch. Unfortunately there's no built-in class like that in Swift, but some implementations could be found online (for example: this class from Uber). So this is a solution:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private let initLatch = CountDownLatch(1)
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
initLatch.countDown()
public func doSomething()
initLatch.await()
// this function should only run after asynch callback was executed
So what does it do:
- the latch is set to 1 so any caller of
doSomethingwill be suspended until latch is decremented to 0 - latch is only decremented to 0 in one place (init completion callback), hence nobody will proceed before initialization completed
- but after latch is set to 0, calling
doSomethingwill not be delayed
Notes:
- This is a simplified model for problem and solution. In reality there are some other factors that may need to be taken into account, and would require other concurrency tools.
- In my case, the callers are non-interactive, hence I do want them to wait rather than be asynchronous. If callers were interactive, I'd let them deal with asynchronous nature of this class instead.
With some help, I found a good solution, that is both reliable and simple. The solution is to use count-down latch. Unfortunately there's no built-in class like that in Swift, but some implementations could be found online (for example: this class from Uber). So this is a solution:
class DataProvider
public static let instance: DataProvider
// on first call wait here until callback is done
// on subsequent calls, no need to wait since already initialized
return internalInstance
private static let internalInstance = DataProvider()
private let initLatch = CountDownLatch(1)
private init()
initialize()
private func initialize()
Something.callAsynch (result, error) in
// instance becomes ready when this line is executed
initLatch.countDown()
public func doSomething()
initLatch.await()
// this function should only run after asynch callback was executed
So what does it do:
- the latch is set to 1 so any caller of
doSomethingwill be suspended until latch is decremented to 0 - latch is only decremented to 0 in one place (init completion callback), hence nobody will proceed before initialization completed
- but after latch is set to 0, calling
doSomethingwill not be delayed
Notes:
- This is a simplified model for problem and solution. In reality there are some other factors that may need to be taken into account, and would require other concurrency tools.
- In my case, the callers are non-interactive, hence I do want them to wait rather than be asynchronous. If callers were interactive, I'd let them deal with asynchronous nature of this class instead.
edited Mar 24 at 19:14
answered Mar 24 at 17:52
Kiril S.Kiril S.
5,81652245
5,81652245
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
add a comment |
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
Thanks for tagging me, this is a pretty elegant solution!
– Augusto Dias Noronha
Mar 24 at 23:00
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%2f55308276%2fhow-to-wait-for-initialization-to-complete-before-returning-a-singleton-instance%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
@George_E I am familiar with them in general, just not sure how to use them in this case. If you have a specific idea, please post, even a gist will do
– Kiril S.
Mar 22 at 21:59
The simplest solution would be to pass a closure as a parameter to
doSomething. While your resource is loading you store the closures in an array. When it's done you call all the closures with the resource. After that you can execute any calls todoSomethingimmediately– Augusto Dias Noronha
Mar 22 at 22:00
@KirilS. Must have not fully understood the question, sorry!
– George_E
Mar 22 at 22:00
A second solution would be to use NSNotificationCenter
– Augusto Dias Noronha
Mar 22 at 22:05
@AugustoDiasNoronha in both cases it pushes responsibility of synchronization to the callers. I was trying to avoid this, since this class only needs to be asynchronous once (on initialization), later it just holds to that static data. I was planning to do initialization early, minimizing the chances that caller needs to wait. So making callers (and there's up to 5 of them) dance around this asynch init problem is less preferable than solving it here within the class itself
– Kiril S.
Mar 22 at 22:16