Подтвердить что ты не робот

Можно ли проверить, существует ли идентификатор в раскадровке перед созданием объекта?

В моем коде у меня есть эта строка, но мне было интересно, существует ли способ проверить, существует ли @SomeController, прежде чем использовать его с методом "instantiateViewControllerWithIdentifier". Если идентификатор не существует, приложение отключается.

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

UIViewController *newTopViewController = [self.storyboard    instantiateViewControllerWithIdentifier:@"SomeController"];
4b9b3361

Ответ 1

Нет, для этого нет никакой проверки. Однако вам это не нужно. Этот метод вернет nil, если идентификатор не существует, поэтому просто проверьте его с помощью NSAssert.

EDIT На самом деле это неправильно! Это странно... раздел возвращаемого значения документации противоречит другой части... но все же ответ в конечном счете отсутствует (нет способа проверить наличие идентификатора)

Ответ 2

Как сказал Том, лучшим решением этой проблемы является блок try-catch:

@try {
        UIViewController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"identifier"];

    }
    @catch (NSException *exception) {
        UIAlertView *catchView;

        catchView = [[UIAlertView alloc]
                     initWithTitle: NSLocalizedString(@"Error", @"Error")
                     message: NSLocalizedString(@"Identifier not found on SB".", @"Error")
                     delegate: self
                     cancelButtonTitle: NSLocalizedString(@"OK", @"Error") otherButtonTitles: nil];

        [catchView show];
    }

Надеюсь, это поможет! хотя ответ действительно задерживается.

Ответ 3

Вы можете использовать valueForKey: на UIStoryboard s. UIStoryboard имеет ключ с именем "identifierToNibNameMap", его значение равно NSDictionary с UIViewController в этой раскадровке. Этот внутренний NSDictionary использует имена viewcontroller как ключи, поэтому вы можете проверить, существует ли viewcontroller в раскадровке со следующим кодом:

if ([[storyboard valueForKey:@"identifierToNibNameMap"] objectForKey:myViewControllerName]) {
    // the view controller exists, instantiate it here
    UIViewController* myViewController = [storyboard instantiateViewControllerWithIdentifier:myViewControllerName];
} else {
    //the view controller doesn't exist, do fallback here
}

Примечание. Apple, как известно, отклоняет приложения, которые запрашивают базовые свойства классов cocoa, используя valueForKey:. Эти базовые свойства могут измениться в любое время в будущем, нарушая функциональность приложения без предупреждения. Для этих вещей нет процесса устаревания.

Ответ 4

Вы можете обернуть код обработкой исключений try-catch и решить, как реагировать, если возникает такое исключение. Я использую этот метод для динамического создания экземпляров контроллеров представлений без необходимости знать, представлены ли они в раскадровке или файле nib.

Ответ 5

Решение @Kevin работает. Вот такой же кусок кода для Swift 3 как функция, которую я использую в своем коде:

func instantiateViewController(fromStoryboardName storyboardName: String, withIdentifier identifier: String) -> UIViewController? {
    let mainStoryboard = UIStoryboard(name: storyboardName, bundle: nil)
    if let availableIdentifiers = mainStoryboard.value(forKey: "identifierToNibNameMap") as? [String: Any] {
        if availableIdentifiers[identifier] != nil {
            if let poiInformationViewController = mainStoryboard.instantiateViewController(withIdentifier: identifier) as? UIViewController {
                return viewController
            }
        }
    }
    return nil
}

Используйте эту функцию следующим образом:

if let viewController = self.instantiateViewController(fromStoryboardName: "YourStoryboardName", withIdentifier: "YourViewControllerStoryboardID") {
    // Here you are sure your viewController is available in the Storyboard
} else {
    print("Error: The Storyboard with the name YourStoryboardName or the Storyboard identifier YourViewControllerStoryboardID is not available")
}