Возвращает переменную из обработчика завершения, которая возвращает void [duplicate]

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
51
задан Mark Tyers 8 August 2014 в 13:28
поделиться

6 ответов

Вы можете передать обратный вызов и вызвать обратный вызов внутри асинхронного вызова

примерно так:

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)")     
    }
}
60
ответ дан Alexey Globchastyy 19 August 2018 в 05:12
поделиться
  • 1
    Спасибо за это. Мой последний вопрос: как я могу вызвать этот метод класса из моего контроллера представления. Код в настоящее время выглядит следующим образом: 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) } – Mark Tyers 8 August 2014 в 13:56
  • 2
    добавил к моему ответу – Alexey Globchastyy 8 August 2014 в 14:00
  • 3
    Спасибо огромное! Вы не поверите, сколько времени я потратил на этот вопрос, прежде чем я нашел ваш ответ! – The_Curry_Man 16 June 2016 в 00:34

Swiftz уже предлагает Future, который является основным строительным блоком Promise. Будущее - это обещание, которое не может потерпеть неудачу (все термины здесь основаны на интерпретации Scala, , где Promise является монадой ).

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

Надеюсь, что в какой-то момент мы сможем написать его в полной версии в стиле Скала (я могу написать это сам в какой-то момент; Конечно, другие PR будут приветствоваться, это не так сложно, если будущее уже на месте).

В вашем конкретном случае я, вероятно, создаю Result<[Book]> (на основе версии Александроса Салазара Result [/ д2]). Тогда ваша сигнатура метода будет:

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

Примечания

  • Я не рекомендую функции префикса с get в Swift. Это нарушит определенные виды совместимости с ObjC.
  • Я рекомендую развернуть весь путь до объекта Book, прежде чем возвращать результаты в качестве Future. Существует несколько способов, с помощью которых эта система может выйти из строя, и гораздо удобнее, если вы проверите все эти вещи, прежде чем обернуть их в Future. Переход к [Book] намного лучше для остальной части вашего кода Swift, чем передача NSArray.
10
ответ дан Community 19 August 2018 в 05:12
поделиться
  • 1
    Swiftz больше не поддерживает Future. Но посмотрите на github.com/mxcl/PromiseKit , он отлично работает с Swiftz! – badeleux 28 July 2015 в 08:45
  • 2
    взял меня на несколько секунд, чтобы понять, что вы не писали Swift и писали Swift z – Honey 18 August 2017 в 19:01
  • 3
    Это звучит как «Swiftz». является сторонней функциональной библиотекой для Swift. Поскольку ваш ответ, похоже, основан на этой библиотеке, вы должны указать это явно. (например, «Существует сторонняя библиотека под названием« Swiftz », которая поддерживает функциональные конструкции, такие как Futures, и должна служить хорошей отправной точкой, если вы хотите реализовать Promises.»). В противном случае ваши читатели просто удивятся, почему вы с ошибкой «Свифт». – Duncan C 2 January 2018 в 22:55
  • 4
    Обратите внимание, что github.com/maxpow4h/swiftz/blob/master/swiftz/Future.swift больше не работает. – Ahmad F 1 March 2018 в 08:16
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()
0
ответ дан CrazyPro007 19 August 2018 в 05:12
поделиться

Другой пример:

class func getExchangeRate(#baseCurrency: String, foreignCurrency:String, completion: ((result:Double?) -> Void)!){
    let baseURL = kAPIEndPoint
    let query = String(baseCurrency)+"_"+String(foreignCurrency)

    var finalExchangeRate = 0.0
    if let url = NSURL(string: baseURL + query) {
        NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in

            if ((data) != nil) {
                let jsonDictionary:NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as NSDictionary

                if let results = jsonDictionary["results"] as? NSDictionary{
                    if let queryResults = results[query] as? NSDictionary{
                        if let exchangeRate = queryResults["val"] as? Double{
                            let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                            dispatch_async(dispatch_get_global_queue(priority, 0)) {
                                dispatch_async(dispatch_get_main_queue()) {
                                    completion(result: exchangeRate)
                                }
                            }

                        }
                    }
                }
            }
            else {
                completion(result: nil)
            }

        }.resume()
    }
}    

Вызов:

 Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in
                if let exchangeValue = result {
                    print(exchangeValue)
                }
            }
8
ответ дан ericgu 19 August 2018 в 05:12
поделиться
  • 1
    Почему вы бы предложили очень конкретный пример обменного курса для вопроса о поиске в книге? Это только путает будущих людей, которые ищут ответ. – jbouaziz 6 November 2017 в 11:34
  • 2
    Потому что его концепция не имеет значения. Сосредоточьтесь на понимании не копирования и вставки – ericgu 4 February 2018 в 20:44
  • 3
    Если это так, то ваш пример слишком специфичен для простой концепции. – jbouaziz 11 February 2018 в 23:29

Swift 4.0

Для async Request-Response вы можете выполнить обработчик завершения пользователем. См. Ниже, я изменил ваше решение с помощью парадигмы обработки завершения.

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 your array
}
1
ответ дан Jaydeep 19 August 2018 в 05:12
поделиться

Свифт 3 версии ответа @Alexey Globchastyy:

class func getGenres(completionHandler: @escaping (genres: NSArray) -> ()) {
...
let task = session.dataTask(with:url) {
    data, response, error in
    ...
    resultsArray = results
    completionHandler(genres: resultsArray)
}
...
task.resume()
}
3
ответ дан Nebojsa Nadj 19 August 2018 в 05:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: