Преобразование пользовательских процедур инициализации в Swift

#objective-c #uinavigationcontroller #initialization #swift #uinavigationitem

#objective-c #uinavigationcontroller #инициализация #swift #uinavigationitem

Вопрос:

Мне нужно создать подкласс SVModalWebViewController.m (GitHub), который сам по себе является подклассом UINavigationController , и я включаю этот код в новое приложение, которое будет создано полностью в Swift. Я столкнулся с несколькими проблемами, поэтому я решил сначала преобразовать только этот очень простой класс в Swift для отладки.

Инициализация в Swift немного отличается от Objective-C (подробнее об инициализации Swift читайте здесь), поэтому я не возвращаюсь self в коде Swift.

Вот исходный код Obj-C (за вычетом *.h, который создает экземпляр barsTintColor ):

 #import "SVModalWebViewController.h"
#import "SVWebViewController.h"

@interface SVModalWebViewController ()

@property (nonatomic, strong) SVWebViewController *webViewController;

@end


@implementation SVModalWebViewController

#pragma mark - Initialization


- (id)initWithAddress:(NSString*)urlString {
    return [self initWithURL:[NSURL URLWithString:urlString]];
}

- (id)initWithURL:(NSURL *)URL {
    self.webViewController = [[SVWebViewController alloc] initWithURL:URL];
    if (self = [super initWithRootViewController:self.webViewController]) {
        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                                                    target:self.webViewController
                                                                                    action:@selector(doneButtonClicked:)];

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
            self.webViewController.navigationItem.leftBarButtonItem = doneButton;
        else
            self.webViewController.navigationItem.rightBarButtonItem = doneButton;
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];

    self.webViewController.title = self.title;
    self.navigationBar.tintColor = self.barsTintColor;
}

@end
  

И вот полная версия класса Swift (я упростил только до одного метода инициализации, поскольку мне не нужно было инициализировать с помощью URL):

 import UIKit

class SVModalWebViewController: UINavigationController {
    var webViewController: SVWebViewController!
    var barsTintColor: UIColor?

    // This was added because of a compiler error indicating it needed to be added
    init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    init(address urlString: String!) {
        let url: NSURL = NSURL.URLWithString(urlString)
        self.webViewController = SVWebViewController(URL: url)
        super.init(rootViewController: self.webViewController)

        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self.webViewController, action: Selector("doneButtonClicked:"))

        if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
            self.navigationItem.leftBarButtonItem = doneButton
        } else {
            self.navigationItem.rightBarButtonItem = doneButton
        }
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // self.title may not be set, and is considered an optional in Swift, so we have to check first
        if self.title {self.webViewController.title = self.title}
        self.navigationBar.tintColor = self.barsTintColor
    }
}
  

Проблема, с которой я сталкиваюсь, связана с установкой Done кнопки в navigationItem . В настоящее время они вообще не отображаются при вызове этого кода:

 let webViewController = SVModalWebViewController(address: "http://www.google.com");
webViewController.barsTintColor = UIColor.blueColor()
self.presentModalViewController(webViewController, animated: true)
  

Модальное представление отображается просто отлично, и я могу правильно установить свойство bar color, но Done кнопка не отображается. Похоже, что у меня нет надлежащего доступа к navigationItem UINavigationController . Обратите внимание, что мне пришлось добавить init с помощью метода nibName из-за ошибки компилятора без него. Это не требовалось в коде Obj-C, и я признаю, что не уверен, зачем это нужно в Swift — это может быть частью проблемы.

Есть мысли о том, почему я не могу установить self.navigationItem.leftBarButtonItem свойство UINavigationController ? Спасибо!

Ответ №1:

UINavigationController не имеет navigationItem . Ну, это так, но это бесполезно. Это navigationItem дочерний контроллер (в данном случае, тот rootViewController , который вы также вызываете self.webViewController ), который появляется на панели навигации.

Комментарии:

1. Вы правы. Изначально у меня был ‘self.WebViewController.navigationItem.leftBarButtonItem = doneButton’, но при отладке был удален ‘WebViewController’. Когда я добавляю «WebViewController», я получаю «не удается развернуть опции». Ошибка отсутствует. Учитывая, что я не создавал экземпляр navigationItem и фактически устанавливаю его здесь (я уже знаю, что это nil), как мне исправить эту ошибку?

2. Да, я перевел много кода с Objective-C на Swift, и я нахожу, что очень, очень легко сделать такую опечатку.

3. Это, по-видимому, потому, что у вас нет webViewController . Но на самом деле это был бы другой вопрос. Я ответил (правильно, я полагаю) на вопрос, который вы задали.

4. Спасибо. Но разве я не должен иметь его к этому моменту? Я вызываю var webViewController: SVWebViewController! в верхней части класса и создаю его экземпляр с self.webViewController = SVWebViewController(URL: url) помощью init, перед рассматриваемым кодом.

5. И, очевидно, этот инициализатор возвращает nil. Я ничего не знаю о SVWebViewController, поэтому я не знаю (или не волнует), почему это так.