web-dev-qa-db-ja.com

Swift URLSessionからデータを返す

HTTPリクエストからデータを返すことができず、完了ハンドラーも機能しません。したがって、この問題を解決するための私の探求で私を助けてください:

public static func createRequest(qMes: message, location: String, method: String) -> String{
    let requestURL = URL(string: location)
    var request = URLRequest(url: requestURL!)

    request.httpMethod = method
    request.httpBody = qMes.toString().data(using: .utf8)

    let requestTask = URLSession.shared.dataTask(with: request) {
        (data: Data?, response: URLResponse?, error: Error?) in

        if(error != nil) {
            print("Error: \(error)")
        }

        return String(data: data!, encoding: String.Encoding.utf8) as String!
    }
    requestTask.resume()
}

Void関数の非void returnステートメントを無視しています。この時点で私は無知です...

10
Craz1k0ek

この完了ブロックメソッドを使用して、最終応答を送信できます。

インスタンスの場合:完了ブロックで文字列を返しました。エラーなしで正常に応答した後、結果をブロックに渡します。

  public func createRequest(qMes: String, location: String, method: String , completionBlock: @escaping (String) -> Void) -> Void
    {

        let requestURL = URL(string: location)
        var request = URLRequest(url: requestURL!)

        request.httpMethod = method
        request.httpBody = qMes.data(using: .utf8)

        let requestTask = URLSession.shared.dataTask(with: request) {
            (data: Data?, response: URLResponse?, error: Error?) in

            if(error != nil) {
                print("Error: \(error)")
            }else
            {

                let outputStr  = String(data: data!, encoding: String.Encoding.utf8) as String!
                //send this block to required place
                completionBlock(outputStr!);
            }
        }
        requestTask.resume()
    } 

以下のコードを使用して、上記の完了ブロック関数を実行できます。

 self.createRequest(qMes: "", location: "", method: "") { (output) in

        }

これにより、次の要件が解決されます。

_{
    (data: Data?, response: URLResponse?, error: Error?) in

    if(error != nil) {
        print("Error: \(error)")
    }

    return String(data: data!, encoding: String.Encoding.utf8) as String!
}
_

コードのこの部分は、dataTask()メソッドの完了ハンドラです。これは、後で実行するためにdataTask()メソッドに渡すコードのブロックです(サーバーがデータを送信したとき、またはエラーが発生したとき)。すぐには実行されません。

これは、上記のcreateRequest()メソッドが実行されている場合、そのコードを直接渡してからrequestTask.resume()行に渡して、メソッドが終了することを意味します。その時点で、メソッドはStringを返すように定義されているため、Stringを返す必要があります。それがまだ実行されていないため、完了ハンドラからそれを返すのはよくありません。後で実行されます。

非同期プログラミングを処理するにはさまざまな方法がありますが、これに取り組む1つの方法は、createRequest()メソッドを変更して、Stringを返すように定義されていないメソッドを作成することです。パラメータとしてのStringは、戻り値を使用してやりたいことをすべて行い、完了ハンドラからそのメソッドを呼び出します。

2
Jim

関数呼び出しだけで

var webString = try String(contentsOf: URL(string: url)!)

そして、あなたは文字列で完全な応答を持っています、あなたは返すことができます

1
Vadim

Returnを使用する代わりに、質問で述べたように完了ハンドラを使用してみてください。

_func createRequest(qMes: message, location: String, method: String, completionHandler: @escaping (_ data:Data?, _ response: URLResponse?, _ error: NSError?) -> Void)
_

次に、returnの代わりにcompletionHandler(data, response, error)のようなものを使用する必要があります

そして、これはあなたがリクエストをする方法です:

_var request = URLRequest(url: Foundation.URL(string: URL)!)
        request.httpMethod = method
        //request.addValue(authString, forHTTPHeaderField: "Authorization") // if you need some

        let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in

            guard error == nil && data != nil else
            {
                print("error=\(error)")
                completionHandler(data, response, error as NSError?)
                return
            }

            completionHandler(data, response, error as NSError?)
        }) 

        task.resume()
_
1
Slavcho