2015-12-29 2 views
5

У меня вопрос об обработке исключений в Swift. Документация UIKit для класса UIStoryboard заявляет, что функция instantiateViewControllerWithIdentifier (идентификатор: String) -> UIViewController генерирует исключение, если идентификатор равен нулю или не существует в раскадровке. Однако, если я использую do/try/catch, как показано ниже, я получаю предупреждение «Нет вызовов для металирования функций в выражении« try ».»обработка исключений с быстрым

Это только предупреждение, поэтому я подумал, что это проблема с intellisense; но когда я запускаю следующий код и намеренно использую недопустимый идентификатор, исключение не попадает и генерируется SIGABRT.

 let storyboard = UIStoryboard.init(name: "Main", bundle: nil) 
    do { 
     let controller = try storyboard.instantiateViewControllerWithIdentifier("SearchPopup") 

     // This code is only included for completeness... 
     controller.modalPresentationStyle = .Popover 
     if let secPopoverPresentationController = controller.popoverPresentationController { 
      secPopoverPresentationController.sourceView = self.view 
      secPopoverPresentationController.permittedArrowDirections = .Any 
      secPopoverPresentationController.barButtonItem = self.bSearchButton 
     } 
     self.presentViewController(controller, animated: true, completion: nil) 
     // End code included for completeness. 
    } 
    catch { 
     NSLog("Exception thrown instantiating view controller."); 
     return; 
    } 

Как вы должны делать/пытаться/улавливать функции, которые генерируют исключения, подобные этому?

Заранее спасибо.

Bryan

+0

См. Этот раздел, Обработка ошибок в быстром режиме: http://iosdevcenters.blogspot.in/2015/12/error-handling-in-swift-20.html –

+0

Спасибо за быстрый ответ. Основная мысль моего вопроса была потеряна во всех деталях. В документации указано исключение IS, но XCode предупреждает, что исключение NO исключено - почему разница? – Bryon

+0

Да, вы получаете RuntimeException, но для статической функции его нет. –

ответ

1

instantiateViewControllerWithIdentifier не является функцией броска, и вы не можете справиться с этим, используя do ... try ... catch. Если контроллер просмотра недоступен в раскадровке, вы ничего не можете сделать. Это ошибка программиста, тот, кто создал это, должен решать такие проблемы. Вы не можете обвинять среду выполнения iOS для таких ошибок.

+1

Спасибо Midhun и @ luk2302. Это имеет смысл для жестко кодированных идентификаторов. Для управляемых данными идентификаторов, которые оставляют немного пробелов для создания пуленепробиваемого приложения, но понимание этого поведения приведет к правильному тестированию. Спасибо! – Bryon

0

Вы не оправиться от этого исключения, что исключением является RuntimeException.
Просто спросите себя: «Как бы я отреагировал на это?» - если ответ «Не знаю», то почему вы даже хотите его поймать?

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

Вы не можете восстановить каким-либо образом, что имеет смысл. Если идентификатор, который вы передаете, не может быть найден, это то, что разработчик сделал неправильно при создании приложения. Это то, что было бы и должно быть очевидным при тестировании приложения. Если вы каким-то образом упустите его, ваше приложение выйдет из строя в обзоре Apple или на устройстве клиента.

+0

Я должен не согласиться. Если вы динамически получаете идентификатор, скажем, через HTTP-запрос, и у вас есть две версии вашего приложения: NewVersion и OldVersion (потому что у вас всегда есть несколько пользователей, которые не обновляют), вам нужно поймать и отреагировать на ошибка в OldVersion. У меня было несколько ситуаций, когда я использую резервный код, чтобы реагировать в старых версиях на код только для новых версий. Например, блок catch может очень хорошо запускать предупреждение, информирующее пользователя, которого он должен обновить, чтобы проверить новый контент, и это только царапает поверхность. – Uzaak

+0

@ Узака с использованием try-catch для обнаружения обновлений звучит крайне плохо. Это все еще не является допустимым вариантом использования для исключения таких исключений. * Если * вы получаете идентификатор из внешнего источника, вы должны * сначала проверить * его, а не просто * использовать * его и отреагировать на полученные исключения. Похоже на плохой дизайн imho. – luk2302

+0

Я полностью согласен с тем, что он должен быть проверен заранее, но Apple не дает нам возможности проверить его. Первоначально, storyboard.instantiateViewControllerWithIdentifier должен был возвращать нуль, когда они не нашли контроллер (как указано в документации), и это нормально. Но он ошибочно сделал исключение. Позже они установили документацию (lol) и сделали исключение броском в общем случае. Таким образом, если не существует способа, чтобы выяснить, существует ли представление, я в настоящее время придерживаюсь этого. Вы знаете какой-нибудь лучший способ? – Uzaak

3

Это конкретный случай более общего вопроса обсуждается в Catching NSException in Swift

Резюме, кажется, что быстрые исключения и исключения ObjC различны.

В этом случае оперативная документация говорит, что он выбрасывает исключение, но это невозможно поймать; что звучит как ошибка документации, по крайней мере.

Я не согласен с другими ответами здесь, что недостающий VC явно является ошибкой программиста. Если поведение было задокументировано, можно постулировать дизайн, в котором общий код реагирует по-разному в зависимости от того, присутствует ли VC или нет в конкретном случае | product | localization. Необходимо добавить дополнительную конфигурацию, чтобы гарантировать, что загрузка VC выполняется только тогда, когда она присутствует, - это приглашение к ошибкам на грани и тому подобное. c.f. обновить аномалии.

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