2015-02-11 2 views
0

В моем приложении iOS у меня есть UIVieController с текстовым полем, которое отправляет запрос каждый раз, когда значение редактируется. Дело в том, чтобы показать предложения пользователей, которые возвращаются с сервера как объект JSON. я изначально имел все запросы Alamofire работать свободно, но чтобы облегчить нагрузку (даже если эти запросы были очень легкими) Я добавилДоступ к ошибке в Alamofire вызывает EXC_BAD_ACCESS

didSet { 
    oldValue?.cancel() 
} 

в modalRequest собственности моего контроллера, который сохраняет текущий запрос.

Однако теперь мой обработчик ответа бросает EXC_BAD_ACCESS (код = 1, адрес = 0x0) при попытке получить доступ к ошибке в закрытии. Код выглядит следующим образом:

@IBAction func textValueChanged(sender: AnyObject) { 
    currentTextField = (sender as UITextField) 

    if (currentTextField!.text != "") { 
     modalRequest = Alamofire.request(.GET, "http://example.org/autocomplete/" + modalType.rawValue, parameters: ["term":currentTextField!.text]).responseJSON {(request, response, json, error) in 
      if let error = error { 
       NSLog("Error: \(error)") 
       println(request) 
       println(response) 
      } else { 
       let oldCount = self.suggestions.count 
       self.suggestions.removeAll() 
       let suggestionJSON = JSON(json!) 
       for s in suggestionJSON.arrayValue { 
        self.suggestions.append(s["name"].stringValue) 
       } 
       self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic) 
      } 
     } 
    } else { 
     self.modalRequest?.cancel() 
     self.suggestions.removeAll() 
     self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic) 
    } 
} 

странной и тревожная часть является то, что, когда я печатаю быстро, тем самым отменяя незавершенные запросы, все идет быстро (каламбур), а это означает, что консоль регистрирует все ошибки в качестве отменена. Однако если введенный текст содержит пробел, а предыдущий запрос отменяется с помощью быстрого ввода, регистратор пытается распечатать ошибку, но выбрасывает EXC_BAD_ACCESS, , хотя он имеет необязательное связывание! Разве это не должно гарантировать, что ценность не равна нулю, по крайней мере, существует?

Вы когда-нибудь сталкивались с этим?

Благодарим вас за внимание!

NB: удаление строки конечно работает, но я мог бы добавить обработку ошибок в будущем, и эта ошибка действительно пристанет мне

ответ

0

Так, чтобы продолжить свой предыдущий комментарий на ответ cnoon в: Я заменил NSLog() с println() и вуаля! Оно работает! Больше нет EXC_BAD_ACCESS.

Однако я не знаю, почему это был плохой доступ. Является ли NSLog чем-то настолько медленным или не копирует значение, так что он равен нулю, когда он, наконец, регистрируется? Я понятия не имею ...

EDIT: Как я уже говорил в моем вопросе, он только разбился, когда запрос содержит пространство. И error.description, который добавляется как-есть к строке, содержит строку URL.Пространство, закодированное в URL-адресе, равно «% 20», поэтому NSLog интерпретировал его как форматировщик строк %2, поэтому он искал второй необязательный аргумент в NSLog, который, конечно, не существовал.! Ха-ха! Таким образом, чтобы действительно красиво это исправить я заменил линию:

NSLog("Error: %@", error) 

Теперь это красивый журнал, без каких-либо икота! Это то, что я получаю для копирования некоторого кода по умолчанию, который объединяет строповую интерполяцию Swift с форматированием строки Objective-C!

+0

Ha! Определенно, никогда бы не подумал, что один из предоставленной информации. Рад, что ты добрался до конца. – cnoon

0

Я думаю, что вы попасться в двух возможных условиях гонки.

  1. Deinit предыдущего modalRequest
  2. A weakify/strongify проблемы с самим

Ниже следует решить обе гонки условий.

@IBAction func textValueChanged(sender: AnyObject) { 
    currentTextField = (sender as UITextField) 

    if (currentTextField!.text != "") { 
     modalRequest?.cancel() 
     modalRequest = nil 

     modalRequest = Alamofire.request(.GET, "http://example.org/autocomplete/" + modalType.rawValue, parameters: ["term":currentTextField!.text]) 
     modelRequest.responseJSON { [weak self] request, response, json, error in 
      if let strongSelf = self { 
       if let error = error { 
        NSLog("Error: \(error)") 
        println(request) 
        println(response) 
       } else { 
        let oldCount = self.suggestions.count 
        self.suggestions.removeAll() 
        let suggestionJSON = JSON(json!) 
        for s in suggestionJSON.arrayValue { 
         self.suggestions.append(s["name"].stringValue) 
        } 
        self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic) 
       } 
      } 
     } 
    } else { 
     self.modalRequest?.cancel() 
     self.suggestions.removeAll() 
     self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic) 
    } 
} 

Если это заканчивается работать, то я предлагаю двигаться следующим образом:

modalRequest?.cancel() 
modalRequest = nil 

в willSet вместо didSet.

willSet { 
    modalRequest?.cancel() 
} 
+0

Большое вам спасибо за ваш ответ. Мне пришлось немного отредактировать его («?» При вызове responseJSON, заменив self на strongSelf и т. Д.), И я попробовал его, и он не исправил проблему. Это привело меня к мысли, что было очень странно, что мое временное исправление (комментирование строки Error) работало, не бросая EXC_BAD_ACCESS для двух строк println(). Поэтому я придумал решение ниже. –

+0

И большое спасибо, потому что я не знал о 'willSet' (которого я не сохранил, потому что, хотя это сработало, вызов' .cancel() 'бросил предупреждение о попытке установить значение в его собственном' willSet ', потому что он будет перезаписан, поэтому я сохранил didSet, потому что он также работает и не предупреждает). И я также узнал о слабых/сильных переменных (о которых я никогда не думал об этом раньше). –

+0

Хорошо, круто. Я бы попробовал '.cancel()' в 'willSet' закрытии. Это имеет смысл, что вы не можете установить его на ноль. Вы в конечном итоге выяснили свой «EXC_BAD_ACCESS»? – cnoon

Смежные вопросы