Wait for Delegate callback to finish the function in Swift
I have a 3rd-party SDK where architecture is like this:
- I call a method of the service (lets call it
TheirService
) - Once that method completes, a delegate of that service (lets call it
TheirServiceDelegate
will receive a notificationonSuccess
if call succeeds oronFailure
if it fails.
The problem with that is that methods of TheirService
are dependant on each other, so I end up having a "chain reaction", where each next method of TheirService
is called from previous callback.
Note that TheirService
is single threaded, and is really picky about previous method to be complete before I can start the next one.
Currently my interactions with the service look like this:
protocol MyClientListener {
notifyOnFailure()
notifyOnResult(result: SomeObject)
}
class MyClient: TheirServiceDelegate {
static let instance = MyClient()
let myService = TheirService()
var myResult: SomeObject?
var resultListener: MyClientListener
private init() { }
func start(resultListener: MyClientListener) {
self.resultListener = resultListener
myService.initialize()
}
// TheirServiceDelegate method
func onInitializeSuccess() {
myService.bootstrap()
}
// TheirServiceDelegate method
func onBootstrapSuccess() {
myService.login(user, password)
}
// TheirServiceDelegate method
func onLoginSuccess() {
myService.doSomethingUsefulStep1()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep1Success() {
myService.doSomethingUsefulStep2()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep2Success(result: SomeObject) {
// ah, look, now I have some object I actually wanted!
resultListener.notifyOnResult(result)
}
}
I also have to deal with failure case for each of them. And I cannot skip or change the order of steps, which creates some sort of awkward state machine.
Instead i would like to interact with service via logical functions, that complete certain stages of the process from end to end, waiting for results between the steps:
class MyClient {
static let instance = MyClient()
let myService = MyService()
private init() { }
func connect() throws {
myService.initialize()
// wait for success or failure, throw on failure
myService.bootstrap()
// wait for success or failure, throw on failure
myService.login(user, password)
// wait for success or failure, throw on failure
}
func doSomethingUseful() -> SomeObject {
myService.doSomethingUsefulStep1()
// wait for success or failure, throw on failure
myService.doSomethingUsefulStep2()
// wait for success or failure, throw on failure
// on success, it will get an object it could return
}
Called like this:
try MyClient.instance.connect()
let x = try MyClient.instance.doSomethingUseful()
So is there any way to turn "wait for success or failure" comment into actual code that waits for that single-threaded service to call back? And where a delegate would fit in that case?
swift
add a comment |
I have a 3rd-party SDK where architecture is like this:
- I call a method of the service (lets call it
TheirService
) - Once that method completes, a delegate of that service (lets call it
TheirServiceDelegate
will receive a notificationonSuccess
if call succeeds oronFailure
if it fails.
The problem with that is that methods of TheirService
are dependant on each other, so I end up having a "chain reaction", where each next method of TheirService
is called from previous callback.
Note that TheirService
is single threaded, and is really picky about previous method to be complete before I can start the next one.
Currently my interactions with the service look like this:
protocol MyClientListener {
notifyOnFailure()
notifyOnResult(result: SomeObject)
}
class MyClient: TheirServiceDelegate {
static let instance = MyClient()
let myService = TheirService()
var myResult: SomeObject?
var resultListener: MyClientListener
private init() { }
func start(resultListener: MyClientListener) {
self.resultListener = resultListener
myService.initialize()
}
// TheirServiceDelegate method
func onInitializeSuccess() {
myService.bootstrap()
}
// TheirServiceDelegate method
func onBootstrapSuccess() {
myService.login(user, password)
}
// TheirServiceDelegate method
func onLoginSuccess() {
myService.doSomethingUsefulStep1()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep1Success() {
myService.doSomethingUsefulStep2()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep2Success(result: SomeObject) {
// ah, look, now I have some object I actually wanted!
resultListener.notifyOnResult(result)
}
}
I also have to deal with failure case for each of them. And I cannot skip or change the order of steps, which creates some sort of awkward state machine.
Instead i would like to interact with service via logical functions, that complete certain stages of the process from end to end, waiting for results between the steps:
class MyClient {
static let instance = MyClient()
let myService = MyService()
private init() { }
func connect() throws {
myService.initialize()
// wait for success or failure, throw on failure
myService.bootstrap()
// wait for success or failure, throw on failure
myService.login(user, password)
// wait for success or failure, throw on failure
}
func doSomethingUseful() -> SomeObject {
myService.doSomethingUsefulStep1()
// wait for success or failure, throw on failure
myService.doSomethingUsefulStep2()
// wait for success or failure, throw on failure
// on success, it will get an object it could return
}
Called like this:
try MyClient.instance.connect()
let x = try MyClient.instance.doSomethingUseful()
So is there any way to turn "wait for success or failure" comment into actual code that waits for that single-threaded service to call back? And where a delegate would fit in that case?
swift
What is theTheirService
? Like link to their files on GitHub?
– impression7vx
Jan 19 at 8:01
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30
add a comment |
I have a 3rd-party SDK where architecture is like this:
- I call a method of the service (lets call it
TheirService
) - Once that method completes, a delegate of that service (lets call it
TheirServiceDelegate
will receive a notificationonSuccess
if call succeeds oronFailure
if it fails.
The problem with that is that methods of TheirService
are dependant on each other, so I end up having a "chain reaction", where each next method of TheirService
is called from previous callback.
Note that TheirService
is single threaded, and is really picky about previous method to be complete before I can start the next one.
Currently my interactions with the service look like this:
protocol MyClientListener {
notifyOnFailure()
notifyOnResult(result: SomeObject)
}
class MyClient: TheirServiceDelegate {
static let instance = MyClient()
let myService = TheirService()
var myResult: SomeObject?
var resultListener: MyClientListener
private init() { }
func start(resultListener: MyClientListener) {
self.resultListener = resultListener
myService.initialize()
}
// TheirServiceDelegate method
func onInitializeSuccess() {
myService.bootstrap()
}
// TheirServiceDelegate method
func onBootstrapSuccess() {
myService.login(user, password)
}
// TheirServiceDelegate method
func onLoginSuccess() {
myService.doSomethingUsefulStep1()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep1Success() {
myService.doSomethingUsefulStep2()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep2Success(result: SomeObject) {
// ah, look, now I have some object I actually wanted!
resultListener.notifyOnResult(result)
}
}
I also have to deal with failure case for each of them. And I cannot skip or change the order of steps, which creates some sort of awkward state machine.
Instead i would like to interact with service via logical functions, that complete certain stages of the process from end to end, waiting for results between the steps:
class MyClient {
static let instance = MyClient()
let myService = MyService()
private init() { }
func connect() throws {
myService.initialize()
// wait for success or failure, throw on failure
myService.bootstrap()
// wait for success or failure, throw on failure
myService.login(user, password)
// wait for success or failure, throw on failure
}
func doSomethingUseful() -> SomeObject {
myService.doSomethingUsefulStep1()
// wait for success or failure, throw on failure
myService.doSomethingUsefulStep2()
// wait for success or failure, throw on failure
// on success, it will get an object it could return
}
Called like this:
try MyClient.instance.connect()
let x = try MyClient.instance.doSomethingUseful()
So is there any way to turn "wait for success or failure" comment into actual code that waits for that single-threaded service to call back? And where a delegate would fit in that case?
swift
I have a 3rd-party SDK where architecture is like this:
- I call a method of the service (lets call it
TheirService
) - Once that method completes, a delegate of that service (lets call it
TheirServiceDelegate
will receive a notificationonSuccess
if call succeeds oronFailure
if it fails.
The problem with that is that methods of TheirService
are dependant on each other, so I end up having a "chain reaction", where each next method of TheirService
is called from previous callback.
Note that TheirService
is single threaded, and is really picky about previous method to be complete before I can start the next one.
Currently my interactions with the service look like this:
protocol MyClientListener {
notifyOnFailure()
notifyOnResult(result: SomeObject)
}
class MyClient: TheirServiceDelegate {
static let instance = MyClient()
let myService = TheirService()
var myResult: SomeObject?
var resultListener: MyClientListener
private init() { }
func start(resultListener: MyClientListener) {
self.resultListener = resultListener
myService.initialize()
}
// TheirServiceDelegate method
func onInitializeSuccess() {
myService.bootstrap()
}
// TheirServiceDelegate method
func onBootstrapSuccess() {
myService.login(user, password)
}
// TheirServiceDelegate method
func onLoginSuccess() {
myService.doSomethingUsefulStep1()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep1Success() {
myService.doSomethingUsefulStep2()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep2Success(result: SomeObject) {
// ah, look, now I have some object I actually wanted!
resultListener.notifyOnResult(result)
}
}
I also have to deal with failure case for each of them. And I cannot skip or change the order of steps, which creates some sort of awkward state machine.
Instead i would like to interact with service via logical functions, that complete certain stages of the process from end to end, waiting for results between the steps:
class MyClient {
static let instance = MyClient()
let myService = MyService()
private init() { }
func connect() throws {
myService.initialize()
// wait for success or failure, throw on failure
myService.bootstrap()
// wait for success or failure, throw on failure
myService.login(user, password)
// wait for success or failure, throw on failure
}
func doSomethingUseful() -> SomeObject {
myService.doSomethingUsefulStep1()
// wait for success or failure, throw on failure
myService.doSomethingUsefulStep2()
// wait for success or failure, throw on failure
// on success, it will get an object it could return
}
Called like this:
try MyClient.instance.connect()
let x = try MyClient.instance.doSomethingUseful()
So is there any way to turn "wait for success or failure" comment into actual code that waits for that single-threaded service to call back? And where a delegate would fit in that case?
swift
swift
asked Jan 18 at 23:53
Kiril S.Kiril S.
5,64352143
5,64352143
What is theTheirService
? Like link to their files on GitHub?
– impression7vx
Jan 19 at 8:01
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30
add a comment |
What is theTheirService
? Like link to their files on GitHub?
– impression7vx
Jan 19 at 8:01
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30
What is the
TheirService
? Like link to their files on GitHub?– impression7vx
Jan 19 at 8:01
What is the
TheirService
? Like link to their files on GitHub?– impression7vx
Jan 19 at 8:01
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30
add a comment |
0
active
oldest
votes
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%2f54262858%2fwait-for-delegate-callback-to-finish-the-function-in-swift%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
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%2f54262858%2fwait-for-delegate-callback-to-finish-the-function-in-swift%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
What is the
TheirService
? Like link to their files on GitHub?– impression7vx
Jan 19 at 8:01
@impression7vx it's not open source, can't provide a link or their source code (I don't have it, all I have is their API which I access via POD, and instructions how to use it, which result in this chain)
– Kiril S.
Jan 21 at 0:30