সুইফট ফাংশনে অ্যাসিঙ্ক কল থেকে ডেটা ফেরানো


93

আমি আমার সুইফট প্রকল্পে একটি ইউটিলিটি ক্লাস তৈরি করেছি যা সমস্ত আরআরইএসটি অনুরোধ এবং প্রতিক্রিয়াগুলি পরিচালনা করে। আমি একটি সাধারণ REST এপিআই তৈরি করেছি যাতে আমি আমার কোড পরীক্ষা করতে পারি। আমি একটি ক্লাস পদ্ধতি তৈরি করেছি যার একটি এনএসআরিকে ফিরিয়ে নেওয়া দরকার তবে এপিআই কল এসিঙ্ক হওয়ায় আমার এসিঙ্ক কলের অভ্যন্তরীন পদ্ধতিটি থেকে ফিরে আসতে হবে। সমস্যাটি হ'ল অ্যাসিঙ্ক রিটার্ন শূন্য। যদি আমি নোডে এটি করছিলাম তবে আমি জেএস প্রতিশ্রুতি ব্যবহার করব তবে আমি সুইফটে কাজ করে এমন কোনও সমাধান বের করতে পারি না।

import Foundation

class Bookshop {
    class func getGenres() -> NSArray {
        println("Hello inside getGenres")
        let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
        println(urlPath)
        let url: NSURL = NSURL(string: urlPath)
        let session = NSURLSession.sharedSession()
        var resultsArray:NSArray!
        let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
            println("Task completed")
            if(error) {
                println(error.localizedDescription)
            }
            var err: NSError?
            var options:NSJSONReadingOptions = NSJSONReadingOptions.MutableContainers
            var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: options, error: &err) as NSDictionary
            if(err != nil) {
                println("JSON Error \(err!.localizedDescription)")
            }
            //NSLog("jsonResults %@", jsonResult)
            let results: NSArray = jsonResult["genres"] as NSArray
            NSLog("jsonResults %@", results)
            resultsArray = results
            return resultsArray // error [anyObject] is not a subType of 'Void'
        })
        task.resume()
        //return "Hello World!"
        // I want to return the NSArray...
    }
}

4
স্ট্যাক ওভারফ্লোতে এই ভুলটি এতটাই সাধারণ যে আমি এর সাথে মোকাবিলা করার জন্য ব্লগ পোস্টগুলির একটি সিরিজ লিখেছি, প্রোগ্রামিংস.এন.টি
ম্যাট

উত্তর:


97

আপনি অ্যাসিঙ্ক কলের মধ্যে কলব্যাক এবং কলব্যাক কল করতে পারেন

কিছুটা এইরকম:

class func getGenres(completionHandler: (genres: NSArray) -> ()) {
    ...
    let task = session.dataTaskWithURL(url) {
        data, response, error in
        ...
        resultsArray = results
        completionHandler(genres: resultsArray)
    }
    ...
    task.resume()
}

এবং তারপরে এই পদ্ধতিটি কল করুন:

override func viewDidLoad() {
    Bookshop.getGenres {
        genres in
        println("View Controller: \(genres)")     
    }
}

তার জন্য ধন্যবাদ. আমার চূড়ান্ত প্রশ্নটি হল আমি কীভাবে এই ক্লাস পদ্ধতিটিকে আমার ভিউ নিয়ন্ত্রক থেকে কল করব। কোডটি বর্তমানে override func viewDidLoad() { super.viewDidLoad() var genres = Bookshop.getGenres() // Missing argument for parameter #1 in call //var genres:NSArray //Bookshop.getGenres(genres) NSLog("View Controller: %@", genres) }
এটির

14

সুইফট ইতিমধ্যে ফিউচার সরবরাহ করে যা একটি প্রতিশ্রুতির প্রাথমিক বিল্ডিং ব্লক। ভবিষ্যত এমন একটি প্রতিশ্রুতি যা ব্যর্থ হতে পারে না (এখানে সমস্ত পদগুলি স্কালার ব্যাখ্যার উপর ভিত্তি করে, যেখানে একটি প্রতিশ্রুতি একটি মোনাড ) ad

https://github.com/maxpow4h/swiftz/blob/master/swiftz/Future.swift

আশা করা যায় শেষ পর্যন্ত একটি সম্পূর্ণ স্কেলা-শৈলীর প্রতিশ্রুতিতে প্রসারিত হবে (আমি নিজেই এটি কোনও সময়ে লিখতে পারি; আমি নিশ্চিত অন্যান্য পিআরএস স্বাগত হবে; ফিউচারের সাথে ইতিমধ্যে এটি ঠিক তেমন কঠিন নয়)।

আপনার নির্দিষ্ট ক্ষেত্রে, আমি সম্ভবত একটি তৈরি করব Result<[Book]>( আলেকজান্দ্রোস সালজারের সংস্করণটিরResult উপর ভিত্তি করে )। তারপরে আপনার পদ্ধতির স্বাক্ষরটি হ'ল:

class func fetchGenres() -> Future<Result<[Book]>> {

মন্তব্য

  • আমি getসুইফট সহ প্রিফিক্সিং ফাংশনগুলির প্রস্তাব দিই না । এটি ওবজিসির সাথে কিছু ধরণের আন্তঃযোগিতা ভেঙে দেবে।
  • Bookহিসাবে আপনার ফলাফলগুলি ফেরত দেওয়ার আগে আমি কোনও উপায়ে সমস্ত উপায়ে পার্স করার পরামর্শ দিচ্ছি Future। এই সিস্টেমটি ব্যর্থ হতে পারে এমন বেশ কয়েকটি উপায় রয়েছে এবং আপনি যদি এগুলি মোড়ানোর আগে এই সমস্ত জিনিস পরীক্ষা করেন তবে এটি আরও বেশি সুবিধাজনক Future। তা পাওয়া [Book]অনেক ভালো একটি প্রায় হস্তান্তর চেয়ে আপনার সুইফট কোড বাকি জন্য NSArray

4
সুইফটজ আর সমর্থন করে না Future। তবে github.com/mxcl/PromiseKit এ দেখুন এটি সুইফটজের সাথে দুর্দান্ত কাজ করে!
ব্লেডলাক্স

আপনি
হানি

4
দেখে মনে হচ্ছে "সুইফটজ" সুইফটের জন্য একটি তৃতীয় পক্ষের ফাংশনাল লাইব্রেরি। যেহেতু আপনার উত্তরটি সেই লাইব্রেরির উপর ভিত্তি করে বলে মনে হচ্ছে, আপনার এটি স্পষ্ট করে বলা উচিত। (যেমন "'সুইফটজ' নামে একটি তৃতীয় পক্ষের গ্রন্থাগার রয়েছে যা ফিউচার্সের মতো কার্যকরী নির্মাণকে সমর্থন করে এবং আপনি যদি প্রতিশ্রুতিগুলি বাস্তবায়ন করতে চান তবে একটি ভাল সূচনা-পয়েন্ট হিসাবে কাজ করা উচিত" ") অন্যথায় আপনার পাঠকরা অবাক হয়ে যাবেন আপনি কেন ভুল বানান বানিয়েছেন" সুইফট "।
ডানকান সি

4
দয়া করে নোট করুন যে github.com/maxpow4h/swiftz/blob/master/swiftz/Future.swift আর কাজ করছে না।
আহমদ এফ

4
@ রব getপ্রিফিক্সটি ওবিজেসি -তে রিটার্ন-বাই-রেফারেন্স নির্দেশ করে (যেমন হিসাবে -[UIColor getRed:green:blue:alpha:])। আমি যখন এটি লিখেছিলাম তখন আমি উদ্বিগ্ন ছিলাম যে আমদানিকারকরা সেই সত্যটি উপার্জন করতে পারবেন (উদাহরণস্বরূপ স্বয়ংক্রিয়ভাবে একটি টুপল ফিরিয়ে দিতে)। দেখা গেল যে তারা নেই। আমি যখন এটি লিখেছিলাম তখন সম্ভবত আমি ভুলে গিয়েছিলাম যে কেভিসি অ্যাক্সেসরগুলির জন্য "পেতে" উপসর্গগুলি সমর্থন করে (এটি এমন কিছু বিষয় যা আমি শিখেছি এবং বেশ কয়েকবার ভুলে গিয়েছি)। তাই সম্মত; নেতৃস্থানীয় getজিনিসগুলি বিরতি দেয় এমন কোনও ক্ষেত্রে আমি যাইনি। এটি কেবল তাদের জন্য বিভ্রান্তিকর যারা ObjC এর অর্থ জানেন "পান"।
রব নেপিয়ার

9

প্রাথমিক প্যাটার্নটি হ'ল সমাপ্তি হ্যান্ডলারের ব্যবহার ব্যবহার করা।

উদাহরণস্বরূপ, আসন্ন সুইফট 5-এ আপনি ব্যবহার করবেন Result:

func fetchGenres(completion: @escaping (Result<[Genre], Error>) -> Void) {
    ...
    URLSession.shared.dataTask(with: request) { data, _, error in 
        if let error = error {
            DispatchQueue.main.async {
                completion(.failure(error))
            }
            return
        }

        // parse response here

        let results = ...
        DispatchQueue.main.async {
            completion(.success(results))
        }
    }.resume()
}

এবং আপনি এটিকে এভাবে ডাকবেন:

fetchGenres { results in
    switch results {
    case .success(let genres):
        // use genres here, e.g. update model and UI

    case .failure(let error):
        print(error.localizedDescription)
    }
}

// but don’t try to use genres here, as the above runs asynchronously

দ্রষ্টব্য, উপরে আমি মডেল এবং ইউআই আপডেটগুলি সহজ করার জন্য পুনরায় মূল সারিতে সমাপ্তি হ্যান্ডলারটি প্রেরণ করছি। কিছু বিকাশকারী এই অনুশীলনের ব্যতিক্রম নেন এবং হয় যা কিছু সারি URLSessionব্যবহৃত হয় তা ব্যবহার করুন বা তাদের নিজস্ব কাত ব্যবহার করুন (কলারকে নিজেই ফলাফলগুলি নিজেই সিঙ্ক্রোনাইজ করার প্রয়োজন হয়)।

তবে এখানে বস্তুগত নয়। মূল সমস্যাটি হ'ল অ্যাসিঙ্ক্রোনাস অনুরোধটি করা হয়ে গেলে কোডটি অবরুদ্ধ করার জন্য কোডটি নির্দিষ্ট করার জন্য সম্পূর্ণকরণ হ্যান্ডলারের ব্যবহার ler


পুরানো, সুইফট 4 প্যাটার্নটি হ'ল:

func fetchGenres(completion: @escaping ([Genre]?, Error?) -> Void) {
    ...
    URLSession.shared.dataTask(with: request) { data, _, error in 
        if let error = error {
            DispatchQueue.main.async {
                completion(nil, error)
            }
            return
        }

        // parse response here

        let results = ...
        DispatchQueue.main.async {
            completion(results, error)
        }
    }.resume()
}

এবং আপনি এটিকে এভাবে ডাকবেন:

fetchGenres { genres, error in
    guard let genres = genres, error == nil else {
        // handle failure to get valid response here

        return
    }

    // use genres here
}

// but don’t try to use genres here, as the above runs asynchronously

দ্রষ্টব্য, উপরে আমি ব্যবহারটি অবসর নিয়েছি NSArray(আমরা সেগুলি ব্রিজযুক্ত অবজেক্টিভ-সি প্রকারগুলি আর ব্যবহার করি না )। আমি ধরে নিই যে আমাদের একটি Genreপ্রকার ছিল এবং আমরা সম্ভবত এটি ডিকোড করার JSONDecoderপরিবর্তে ব্যবহার JSONSerializationকরি। তবে এই প্রশ্নের এখানে বিশদটি জানতে under


আপনি Resultসুইফট 4 এবং নিম্নেও ব্যবহার করতে পারেন তবে আপনাকে এনামটি নিজেই ঘোষণা করতে হবে। আমি বছরের পর বছর ধরে এই ধরণের ব্যবহার করছি।
ভাদিয়ান

হ্যাঁ, অবশ্যই আমার মতো আছে have তবে এটি কেবল দেখে মনে হচ্ছে এটি সুইট 5 রিলিজের সাথে অ্যাপল গ্রহণ করেছে They তারা পার্টিতে খুব দেরি করেছে।
রব

7

সুইফট 4.0

অ্যাসিঙ্ক অনুরোধ-প্রতিক্রিয়া জন্য আপনি সম্পূর্ণ হ্যান্ডলার ব্যবহার করতে পারেন। নীচে দেখুন আমি সম্পূর্ণরূপে হ্যান্ডেল দৃষ্টান্ত দিয়ে সমাধানটি সংশোধন করেছি।

func getGenres(_ completion: @escaping (NSArray) -> ()) {

        let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
        print(urlPath)

        guard let url = URL(string: urlPath) else { return }

        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else { return }
            do {
                if let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                    let results = jsonResult["genres"] as! NSArray
                    print(results)
                    completion(results)
                }
            } catch {
                //Catch Error here...
            }
        }
        task.resume()
    }

আপনি নীচে হিসাবে এই ফাংশন কল করতে পারেন:

getGenres { (array) in
    // Do operation with array
}

2

@ অ্যালেক্সি গ্লোবচস্টির উত্তরের সুইফট 3 সংস্করণ:

class func getGenres(completionHandler: @escaping (genres: NSArray) -> ()) {
...
let task = session.dataTask(with:url) {
    data, response, error in
    ...
    resultsArray = results
    completionHandler(genres: resultsArray)
}
...
task.resume()
}

2

আমি আশা করি আপনি এখনও এটিতে আটকে থাকেন না, তবে সংক্ষিপ্ত উত্তরটি হ'ল আপনি সুইফটে এটি করতে পারবেন না।

একটি বিকল্প পন্থা হ'ল একটি কলব্যাক ফিরিয়ে দেওয়া যা এটি প্রস্তুত হওয়ার সাথে সাথে আপনার প্রয়োজনীয় ডেটা সরবরাহ করবে।


4
তিনি দ্রুত প্রতিশ্রুতি করতে পারেন। কিন্তু অ্যাপলের বর্তমান প্রস্তাবিত aproceh ব্যবহার করছে callbackসঙ্গে closureগুলি আপনি খুঁজে বাতলান বা ব্যবহার করতে যেমন delegationপুরোনো কোকো এপিআই এর মত
Mojtaba Hosseini

প্রতিশ্রুতি সম্পর্কে আপনি ঠিক। তবে সুইফ্ট এটির জন্য কোনও দেশীয় এপিআই সরবরাহ করে না, সুতরাং তাকে প্রমিসকিট বা অন্যান্য বিকল্প ব্যবহার করতে হবে।
লিরনএক্সইজেড

1

কল ব্যাক ফাংশন তৈরির 3 উপায় রয়েছে যথা: 1. সম্পূর্ণ হ্যান্ডলার 2. বিজ্ঞপ্তি 3. প্রতিনিধি 3.

সম্পূর্ণ হ্যান্ডলার ব্লকের সেট এর সেটটি কার্যকর করা হয় এবং উত্স উপলব্ধ হলে ফিরে আসে, হ্যান্ডলার প্রতিক্রিয়া না আসা পর্যন্ত অপেক্ষা করবে যাতে ইউআই পরে আপডেট করা যায়।

বিজ্ঞপ্তি গুচ্ছ তথ্য সমস্ত অ্যাপ্লিকেশন উপর ট্রিগার করা হয়, তালিকাভুক্ত তথ্য পুনরুদ্ধার করতে পারেন তথ্য ব্যবহার করে। প্রকল্পের মাধ্যমে তথ্য পাওয়ার অ্যাসিঙ্ক উপায়।

প্রতিনিধিদের ডাকা হওয়ার সময় ডেলিগেটস পদ্ধতির সেটটি ট্রিগার হয়ে উঠবে, উত্সটি অবশ্যই পদ্ধতিগুলির মাধ্যমে সরবরাহ করতে হবে


-1
self.urlSession.dataTask(with: request, completionHandler: { (data, response, error) in
            self.endNetworkActivity()

            var responseError: Error? = error
            // handle http response status
            if let httpResponse = response as? HTTPURLResponse {

                if httpResponse.statusCode > 299 , httpResponse.statusCode != 422  {
                    responseError = NSError.errorForHTTPStatus(httpResponse.statusCode)
                }
            }

            var apiResponse: Response
            if let _ = responseError {
                apiResponse = Response(request, response as? HTTPURLResponse, responseError!)
                self.logError(apiResponse.error!, request: request)

                // Handle if access token is invalid
                if let nsError: NSError = responseError as NSError? , nsError.code == 401 {
                    DispatchQueue.main.async {
                        apiResponse = Response(request, response as? HTTPURLResponse, data!)
                        let message = apiResponse.message()
                        // Unautorized access
                        // User logout
                        return
                    }
                }
                else if let nsError: NSError = responseError as NSError? , nsError.code == 503 {
                    DispatchQueue.main.async {
                        apiResponse = Response(request, response as? HTTPURLResponse, data!)
                        let message = apiResponse.message()
                        // Down time
                        // Server is currently down due to some maintenance
                        return
                    }
                }

            } else {
                apiResponse = Response(request, response as? HTTPURLResponse, data!)
                self.logResponse(data!, forRequest: request)
            }

            self.removeRequestedURL(request.url!)

            DispatchQueue.main.async(execute: { () -> Void in
                completionHandler(apiResponse)
            })
        }).resume()

-1

সুইফটে কলব্যাক অর্জনের মূলত 3 টি উপায় রয়েছে

  1. বন্ধ / সমাপ্তি হ্যান্ডলার

  2. প্রতিনিধিরা

  3. বিজ্ঞপ্তি

অ্যাসিঙ্ক টাস্কটি শেষ হয়ে গেলে পর্যবেক্ষকরাও বিজ্ঞপ্তি পেতে ব্যবহার করতে পারেন।


-2

কিছু খুব জেনেরিক প্রয়োজনীয়তা রয়েছে যা প্রতিটি ভাল এপিআই ম্যানেজার সন্তুষ্ট করতে চায়: একটি প্রোটোকল ভিত্তিক এপিআই ক্লায়েন্ট বাস্তবায়ন করবে

এপিক্লিয়েন্ট ইনিশিয়াল ইন্টারফেস

protocol APIClient {
   func send(_ request: APIRequest,
              completion: @escaping (APIResponse?, Error?) -> Void) 
}

protocol APIRequest: Encodable {
    var resourceName: String { get }
}

protocol APIResponse: Decodable {
}

এখন দয়া করে সম্পূর্ণ এপিআই কাঠামো পরীক্ষা করুন

// ******* This is API Call Class  *****
public typealias ResultCallback<Value> = (Result<Value, Error>) -> Void

/// Implementation of a generic-based  API client
public class APIClient {
    private let baseEndpointUrl = URL(string: "irl")!
    private let session = URLSession(configuration: .default)

    public init() {

    }

    /// Sends a request to servers, calling the completion method when finished
    public func send<T: APIRequest>(_ request: T, completion: @escaping ResultCallback<DataContainer<T.Response>>) {
        let endpoint = self.endpoint(for: request)

        let task = session.dataTask(with: URLRequest(url: endpoint)) { data, response, error in
            if let data = data {
                do {
                    // Decode the top level response, and look up the decoded response to see
                    // if it's a success or a failure
                    let apiResponse = try JSONDecoder().decode(APIResponse<T.Response>.self, from: data)

                    if let dataContainer = apiResponse.data {
                        completion(.success(dataContainer))
                    } else if let message = apiResponse.message {
                        completion(.failure(APIError.server(message: message)))
                    } else {
                        completion(.failure(APIError.decoding))
                    }
                } catch {
                    completion(.failure(error))
                }
            } else if let error = error {
                completion(.failure(error))
            }
        }
        task.resume()
    }

    /// Encodes a URL based on the given request
    /// Everything needed for a public request to api servers is encoded directly in this URL
    private func endpoint<T: APIRequest>(for request: T) -> URL {
        guard let baseUrl = URL(string: request.resourceName, relativeTo: baseEndpointUrl) else {
            fatalError("Bad resourceName: \(request.resourceName)")
        }

        var components = URLComponents(url: baseUrl, resolvingAgainstBaseURL: true)!

        // Common query items needed for all api requests
        let timestamp = "\(Date().timeIntervalSince1970)"
        let hash = "\(timestamp)"
        let commonQueryItems = [
            URLQueryItem(name: "ts", value: timestamp),
            URLQueryItem(name: "hash", value: hash),
            URLQueryItem(name: "apikey", value: "")
        ]

        // Custom query items needed for this specific request
        let customQueryItems: [URLQueryItem]

        do {
            customQueryItems = try URLQueryItemEncoder.encode(request)
        } catch {
            fatalError("Wrong parameters: \(error)")
        }

        components.queryItems = commonQueryItems + customQueryItems

        // Construct the final URL with all the previous data
        return components.url!
    }
}

// ******  API Request Encodable Protocol *****
public protocol APIRequest: Encodable {
    /// Response (will be wrapped with a DataContainer)
    associatedtype Response: Decodable

    /// Endpoint for this request (the last part of the URL)
    var resourceName: String { get }
}

// ****** This Results type  Data Container Struct ******
public struct DataContainer<Results: Decodable>: Decodable {
    public let offset: Int
    public let limit: Int
    public let total: Int
    public let count: Int
    public let results: Results
}
// ***** API Errro Enum ****
public enum APIError: Error {
    case encoding
    case decoding
    case server(message: String)
}


// ****** API Response Struct ******
public struct APIResponse<Response: Decodable>: Decodable {
    /// Whether it was ok or not
    public let status: String?
    /// Message that usually gives more information about some error
    public let message: String?
    /// Requested data
    public let data: DataContainer<Response>?
}

// ***** URL Query Encoder OR JSON Encoder *****
enum URLQueryItemEncoder {
    static func encode<T: Encodable>(_ encodable: T) throws -> [URLQueryItem] {
        let parametersData = try JSONEncoder().encode(encodable)
        let parameters = try JSONDecoder().decode([String: HTTPParam].self, from: parametersData)
        return parameters.map { URLQueryItem(name: $0, value: $1.description) }
    }
}

// ****** HTTP Pamater Conversion Enum *****
enum HTTPParam: CustomStringConvertible, Decodable {
    case string(String)
    case bool(Bool)
    case int(Int)
    case double(Double)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()

        if let string = try? container.decode(String.self) {
            self = .string(string)
        } else if let bool = try? container.decode(Bool.self) {
            self = .bool(bool)
        } else if let int = try? container.decode(Int.self) {
            self = .int(int)
        } else if let double = try? container.decode(Double.self) {
            self = .double(double)
        } else {
            throw APIError.decoding
        }
    }

    var description: String {
        switch self {
        case .string(let string):
            return string
        case .bool(let bool):
            return String(describing: bool)
        case .int(let int):
            return String(describing: int)
        case .double(let double):
            return String(describing: double)
        }
    }
}

/// **** This is your API Request Endpoint  Method in Struct *****
public struct GetCharacters: APIRequest {
    public typealias Response = [MyCharacter]

    public var resourceName: String {
        return "characters"
    }

    // Parameters
    public let name: String?
    public let nameStartsWith: String?
    public let limit: Int?
    public let offset: Int?

    // Note that nil parameters will not be used
    public init(name: String? = nil,
                nameStartsWith: String? = nil,
                limit: Int? = nil,
                offset: Int? = nil) {
        self.name = name
        self.nameStartsWith = nameStartsWith
        self.limit = limit
        self.offset = offset
    }
}

// *** This is Model for Above Api endpoint method ****
public struct MyCharacter: Decodable {
    public let id: Int
    public let name: String?
    public let description: String?
}


// ***** These below line you used to call any api call in your controller or view model ****
func viewDidLoad() {
    let apiClient = APIClient()

    // A simple request with no parameters
    apiClient.send(GetCharacters()) { response in

        response.map { dataContainer in
            print(dataContainer.results)
        }
    }

}

-2

এটি একটি ছোট ব্যবহারের কেস যা সহায়ক হতে পারে: -

func testUrlSession(urlStr:String, completionHandler: @escaping ((String) -> Void)) {
        let url = URL(string: urlStr)!


        let task = URLSession.shared.dataTask(with: url){(data, response, error) in
            guard let data = data else { return }
            if let strContent = String(data: data, encoding: .utf8) {
            completionHandler(strContent)
            }
        }


        task.resume()
    }

ফাংশনটি কল করার সময়: -

testUrlSession(urlStr: "YOUR-URL") { (value) in
            print("Your string value ::- \(value)")
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.