user14295707
user14295707

Reputation:

Return value from Function in swift

I have a function which is a part of some WebScraping Code. Pretty "deep" in the function I have a value which I want to display in a chart. To do that I need to get the variable "elevation" out of the function parseElevation(). I have tried

func parseElevation() -> String {

This however doesn't work because the variable "elevation" is "one layer deeper.

This is the code:

func parseElevation()  {
        webView.evaluateJavaScript("document.body.innerHTML") { result, error in
            guard let html = result as? String, error == nil else {
                return
            }
            
            let leftSideOfTheValue = """
            <pre style="word-wrap: break-word; white-space: pre-wrap;">
            """
            
            let rightSideOfTheValue = """
            </pre>
            """
            
            guard let leftRange = html.range(of: leftSideOfTheValue) else {
                print("cant find left range")
                return
            }
            
            guard let righRange = html.range(of: rightSideOfTheValue) else {
                print("cant find right range")
                return
            }
            
            let rangeOfTheValue = leftRange.upperBound..<righRange.lowerBound
            
            let elevationInfo = (html[rangeOfTheValue])
            
            let last9 = elevationInfo.suffix(11)
            
            if let index = (last9.range(of: ",")?.upperBound)
            {
              //prints "value"
              let afterEqualsTo = String(last9.suffix(from: index))
                print(afterEqualsTo)
                let elevation = afterEqualsTo
                
            }
        }
        
    }

Does somebody have an idea how to solve this problem. I have always had a problem with returning values in swift.

Upvotes: 0

Views: 581

Answers (1)

vadian
vadian

Reputation: 285069

You cannot return something from a closure which doesn't have a return value.

You need an asynchronous completion handler

func parseElevation(completion: @escaping (String) -> Void)  {
    webView.evaluateJavaScript("document.body.innerHTML") { result, error in
        guard let html = result as? String, error == nil else {
            return
        }
        
        let leftSideOfTheValue = """
        <pre style="word-wrap: break-word; white-space: pre-wrap;">
        """
        
        let rightSideOfTheValue = """
        </pre>
        """
        
        guard let leftRange = html.range(of: leftSideOfTheValue) else {
            print("cant find left range")
            return
        }
        
        guard let righRange = html.range(of: rightSideOfTheValue) else {
            print("cant find right range")
            return
        }
        
        let rangeOfTheValue = leftRange.upperBound..<righRange.lowerBound
        
        let elevationInfo = (html[rangeOfTheValue])
        
        let last9 = elevationInfo.suffix(11)
        
        if let index = (last9.range(of: ",")?.upperBound)
        {
            //prints "value"
            let afterEqualsTo = String(last9.suffix(from: index))
            completion(afterEqualsTo)                
        }
    } 
}

and call it

parseElevation { elevation in
    print(elevation)
}

Notes:

  • elevation in the second snippet is only available inside the closure {}.

  • Consider that the completion handler is only called if a result is evaluated. All return statements leave the closure silently.

Upvotes: 2

Related Questions