Swift calling completion handler in from another file fails
I am calling a funciton with completio=n handler from one calss to another class
Called class:
class PVClass
{
var avgMonthlyAcKw:Double = 0.0
var jsonString:String!
func estimateMonthlyACkW (areaSqFt:Float, completion: @escaping(Double) -> () ){
var capacityStr:String = ""
let estimatedCapacity = Float(areaSqFt/66.0)
capacityStr = String(format: "%.2f", estimatedCapacity)
// Build some Url string
var urlString:String = "https://developer.nrel.gov/"
urlString.append("&system_capacity=")
urlString.append(capacityStr)
let pvURL = URL(string: urlString)
let dataTask = URLSession.shared.dataTask(with: pvURL!) { data, response, error in
do {
let _ = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
self.jsonString = String(data: data!, encoding: .utf8)!
print("JSON String:(String(describing: self.jsonString))")
if self.jsonString != nil {
let decoder = JSONDecoder()
let jsonData = try decoder.decode(PVClass.Top.self, from: data!)
// do some parsing here
var totalAcKw: Double = 0.0
let cnt2: Int = (jsonData.Outputs?.ACMonthly.count)!
for i in 0..<(cnt2-1) {
totalAcKw = totalAcKw + (jsonData.Outputs?.ACMonthly[i])!
}
self.avgMonthlyAcKw = Double(totalAcKw)/Double(cnt2)
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
}
} catch {
print("error: (error.localizedDescription)")
}
}
dataTask.resume()
completion(self.avgMonthlyAcKw)
}
Calling Class:
func estimate() {
var estimatedSolarkWh:Double = 0.0
let aPVClass = PVClass()
aPVClass.estimateMonthlyACkW(areaSqFt: 100.0, completion: { (monthlyAckW) -> Void in
estimatedSolarkWh = monthlyAckW
self.view.setNeedsDisplay()
})
return
}
}
When I call the function estimate() the estimateMonthlyACkW function in the other PVClass is executed but it returns after the calling estimate() function is executed. So even though in the called function the URLsession is executed, json is parsed, and value is printed correctly - the value never gets gets transferred to the completion handler and the value never comes back to calling class. How can I fix this?
swift completionhandler
add a comment |
I am calling a funciton with completio=n handler from one calss to another class
Called class:
class PVClass
{
var avgMonthlyAcKw:Double = 0.0
var jsonString:String!
func estimateMonthlyACkW (areaSqFt:Float, completion: @escaping(Double) -> () ){
var capacityStr:String = ""
let estimatedCapacity = Float(areaSqFt/66.0)
capacityStr = String(format: "%.2f", estimatedCapacity)
// Build some Url string
var urlString:String = "https://developer.nrel.gov/"
urlString.append("&system_capacity=")
urlString.append(capacityStr)
let pvURL = URL(string: urlString)
let dataTask = URLSession.shared.dataTask(with: pvURL!) { data, response, error in
do {
let _ = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
self.jsonString = String(data: data!, encoding: .utf8)!
print("JSON String:(String(describing: self.jsonString))")
if self.jsonString != nil {
let decoder = JSONDecoder()
let jsonData = try decoder.decode(PVClass.Top.self, from: data!)
// do some parsing here
var totalAcKw: Double = 0.0
let cnt2: Int = (jsonData.Outputs?.ACMonthly.count)!
for i in 0..<(cnt2-1) {
totalAcKw = totalAcKw + (jsonData.Outputs?.ACMonthly[i])!
}
self.avgMonthlyAcKw = Double(totalAcKw)/Double(cnt2)
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
}
} catch {
print("error: (error.localizedDescription)")
}
}
dataTask.resume()
completion(self.avgMonthlyAcKw)
}
Calling Class:
func estimate() {
var estimatedSolarkWh:Double = 0.0
let aPVClass = PVClass()
aPVClass.estimateMonthlyACkW(areaSqFt: 100.0, completion: { (monthlyAckW) -> Void in
estimatedSolarkWh = monthlyAckW
self.view.setNeedsDisplay()
})
return
}
}
When I call the function estimate() the estimateMonthlyACkW function in the other PVClass is executed but it returns after the calling estimate() function is executed. So even though in the called function the URLsession is executed, json is parsed, and value is printed correctly - the value never gets gets transferred to the completion handler and the value never comes back to calling class. How can I fix this?
swift completionhandler
add a comment |
I am calling a funciton with completio=n handler from one calss to another class
Called class:
class PVClass
{
var avgMonthlyAcKw:Double = 0.0
var jsonString:String!
func estimateMonthlyACkW (areaSqFt:Float, completion: @escaping(Double) -> () ){
var capacityStr:String = ""
let estimatedCapacity = Float(areaSqFt/66.0)
capacityStr = String(format: "%.2f", estimatedCapacity)
// Build some Url string
var urlString:String = "https://developer.nrel.gov/"
urlString.append("&system_capacity=")
urlString.append(capacityStr)
let pvURL = URL(string: urlString)
let dataTask = URLSession.shared.dataTask(with: pvURL!) { data, response, error in
do {
let _ = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
self.jsonString = String(data: data!, encoding: .utf8)!
print("JSON String:(String(describing: self.jsonString))")
if self.jsonString != nil {
let decoder = JSONDecoder()
let jsonData = try decoder.decode(PVClass.Top.self, from: data!)
// do some parsing here
var totalAcKw: Double = 0.0
let cnt2: Int = (jsonData.Outputs?.ACMonthly.count)!
for i in 0..<(cnt2-1) {
totalAcKw = totalAcKw + (jsonData.Outputs?.ACMonthly[i])!
}
self.avgMonthlyAcKw = Double(totalAcKw)/Double(cnt2)
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
}
} catch {
print("error: (error.localizedDescription)")
}
}
dataTask.resume()
completion(self.avgMonthlyAcKw)
}
Calling Class:
func estimate() {
var estimatedSolarkWh:Double = 0.0
let aPVClass = PVClass()
aPVClass.estimateMonthlyACkW(areaSqFt: 100.0, completion: { (monthlyAckW) -> Void in
estimatedSolarkWh = monthlyAckW
self.view.setNeedsDisplay()
})
return
}
}
When I call the function estimate() the estimateMonthlyACkW function in the other PVClass is executed but it returns after the calling estimate() function is executed. So even though in the called function the URLsession is executed, json is parsed, and value is printed correctly - the value never gets gets transferred to the completion handler and the value never comes back to calling class. How can I fix this?
swift completionhandler
I am calling a funciton with completio=n handler from one calss to another class
Called class:
class PVClass
{
var avgMonthlyAcKw:Double = 0.0
var jsonString:String!
func estimateMonthlyACkW (areaSqFt:Float, completion: @escaping(Double) -> () ){
var capacityStr:String = ""
let estimatedCapacity = Float(areaSqFt/66.0)
capacityStr = String(format: "%.2f", estimatedCapacity)
// Build some Url string
var urlString:String = "https://developer.nrel.gov/"
urlString.append("&system_capacity=")
urlString.append(capacityStr)
let pvURL = URL(string: urlString)
let dataTask = URLSession.shared.dataTask(with: pvURL!) { data, response, error in
do {
let _ = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
self.jsonString = String(data: data!, encoding: .utf8)!
print("JSON String:(String(describing: self.jsonString))")
if self.jsonString != nil {
let decoder = JSONDecoder()
let jsonData = try decoder.decode(PVClass.Top.self, from: data!)
// do some parsing here
var totalAcKw: Double = 0.0
let cnt2: Int = (jsonData.Outputs?.ACMonthly.count)!
for i in 0..<(cnt2-1) {
totalAcKw = totalAcKw + (jsonData.Outputs?.ACMonthly[i])!
}
self.avgMonthlyAcKw = Double(totalAcKw)/Double(cnt2)
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
}
} catch {
print("error: (error.localizedDescription)")
}
}
dataTask.resume()
completion(self.avgMonthlyAcKw)
}
Calling Class:
func estimate() {
var estimatedSolarkWh:Double = 0.0
let aPVClass = PVClass()
aPVClass.estimateMonthlyACkW(areaSqFt: 100.0, completion: { (monthlyAckW) -> Void in
estimatedSolarkWh = monthlyAckW
self.view.setNeedsDisplay()
})
return
}
}
When I call the function estimate() the estimateMonthlyACkW function in the other PVClass is executed but it returns after the calling estimate() function is executed. So even though in the called function the URLsession is executed, json is parsed, and value is printed correctly - the value never gets gets transferred to the completion handler and the value never comes back to calling class. How can I fix this?
swift completionhandler
swift completionhandler
asked Dec 29 '18 at 6:08
vraovrao
1662519
1662519
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You need to move completion(self.avgMonthlyAcKw)
just after print statement like below:
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
Hope this will helps you :)
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
|
show 3 more comments
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%2f53967157%2fswift-calling-completion-handler-in-from-another-file-fails%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
You need to move completion(self.avgMonthlyAcKw)
just after print statement like below:
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
Hope this will helps you :)
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
|
show 3 more comments
You need to move completion(self.avgMonthlyAcKw)
just after print statement like below:
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
Hope this will helps you :)
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
|
show 3 more comments
You need to move completion(self.avgMonthlyAcKw)
just after print statement like below:
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
Hope this will helps you :)
You need to move completion(self.avgMonthlyAcKw)
just after print statement like below:
// prints value
print("updated estimate: ", self.avgMonthlyAcKw)
completion(self.avgMonthlyAcKw)
Hope this will helps you :)
answered Dec 29 '18 at 6:15
iVaruniVarun
3,66421325
3,66421325
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
|
show 3 more comments
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
I did that and does not work. I dont know why
– vrao
Dec 29 '18 at 16:12
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Updated comment: I did that the completion handler gets called I capture the return value in var estimatedSolarkWh. I make the assignment from the var estimatedSolarkWh to the UI, but the UI does not get updated . How to force the UI refresh based on the captured value?
– vrao
Dec 29 '18 at 16:40
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
Add UI stuff in DispatchQueue.main.async{ }
– iVarun
Dec 29 '18 at 16:43
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
@vrao did this work for you?
– iVarun
Dec 29 '18 at 16:53
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
Modified code still fails. DispatchQueue.main.async { [weak self] in guard case self = self else { return } print("monthlyAckW: ", monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?.numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else { return } print("val: ", val) self?.estimatedSolarkWhLabel.text = String(val) self?.view.setNeedsDisplay()} })
– vrao
Dec 29 '18 at 16:56
|
show 3 more comments
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%2f53967157%2fswift-calling-completion-handler-in-from-another-file-fails%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