Как Инициализировать Многоразовый NSView Встроенный Интерфейсный Разработчик (Поддержанный Xib) Без ViewController - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь создать многоразовое представление, которое я могу программным образом создать для нескольких копий в суперпредставлении.Однако я хотел бы обработать ограничения и базовую компоновку этого повторно используемого представления в Интерфейсном Разработчике.Для моего суперпредставления у меня есть подкласс NSViewController, подкласс NSView и файл xib.В ViewDidLoad моего ViewController у меня есть такой код для создания дочерних представлений:

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    var exampleView = new NSView();

    View.AddSubview(exampleView);
    View.AddConstraints(CreateExampleViewConstraints(exampleView, View));

    NSView lastView = null;
    foreach(var item in ExampleCollection)
    {
            var reuseableView = ReusableView.Create(item);
            reuseableView.TranslatesAutoresizingMaskIntoConstraints = false;

            exampleView.AddSubview(reuseableView);
            var xPosConstraint = NSLayoutConstraint.Create(reuseableView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, exampleView, NSLayoutAttribute.Left, 1, 0);
            NSLayoutConstraint yPosConstraint = null;
            if(lastView != null)
            {
                yPosConstraint = NSLayoutConstraint.Create(reuseableView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, lastView, NSLayoutAttribute.Bottom, 1, 0);
            }
            else
            {
                yPosConstraint = NSLayoutConstraint.Create(reuseableView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, exampleView, NSLayoutAttribute.Top, 1, 0);
            }
            var widthConstraint = NSLayoutConstraint.Create(reuseableView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, exampleView, NSLayoutAttribute.Width, 1, 0);
            var heightConstraint = NSLayoutConstraint.Create(reuseableView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1, 142);
            exampleView.AddConstraint(xPosConstraint);
            exampleView.AddConstraint(yPosConstraint);
            exampleView.AddConstraint(widthConstraint);
            exampleView.AddConstraint(heightConstraint);

            lastView = reuseableView;
        }
    }

    if(lastView != null)
    {
        var bottomPinConstraint = NSLayoutConstraint.Create(exampleView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, lastView, NSLayoutAttribute.Bottom, 1, 0);
        exampleView.AddConstraint(bottomPinConstraint);
    }
}

Ограничения не важны для проблемы, которую я пытаюсь решить.ReusableView - это подкласс NSView, который имеет 3 NSTextField розеток с именами TitleLabel, DateLabel и LocationLabel:

public partial class ReusableView : AppKit.NSView
{
    string _title;
    string _date;
    string _location;

    public ReusableView(IntPtr handle) : base(handle)
    {
    }

    [Export("initWithCoder:")]
    public ReusableView(NSCoder coder) : base(coder)
    {
    }

    public static ReusableView Create(ExampleDependency dependency)
    {
        var model = dependency ?? throw new ArgumentNullException(nameof(dependency));
        NSBundle.MainBundle.LoadNibNamed(nameof(ReusableView), null, out var array);
        var view = NSArray.FromArray<NSObject>(array).OfType<ReusableView>().FirstOrDefault();
        view.Initialize(model);
        return view;
    }

    private void Initialize(ExampleDependency dependency)
    {
        _title = dependency.name;
        _date = dependency.date;
        _location = $"{dependency.eventCity}, {dependency.eventState}";
    }

    public void UpdateControls()
    {
        TitleLabel.StringValue = _title;
        DateLabel.StringValue = _date;
        LocationLabel.StringValue = _location;
    }
}

Проблема, с которой я сталкиваюсь:Время, в течение которого методы жизненного цикла ViewController перед отображением являются подключенными / ненулевыми IBOutlets из ReusableView.Как вы видите, у меня есть открытый метод с именем UpdateControls(), чтобы попытаться установить начальные значения меток на основе приватных полей, которые инициализируются во время Create().Метод Create() успешно загружает XIB и возвращает экземпляр ReusableView;Я даже могу видеть представления и значения заполнителей во время выполнения.Тем не менее, я пытался вызвать UpdateControls() во время AwakeFromNib() и ViewWillAppear() методов контроллера представления суперпредставления, но всегда получаю исключение нулевой ссылки, потому что ни один из выходов, по-видимому, еще не создан.

IОчевидно, что можно полностью программно создать ReusableView и установить мои ограничения для элементов управления в коде, но я пытаюсь использовать конструктор интерфейса.Есть ли способ сделать это?

1 Ответ

0 голосов
/ 26 июня 2018

Я не смог заставить это работать без добавления View Controller для моего многоразового представления.В Xamarin я использовал шаблон Mac > View with Controller и изложил все свои ограничения в сгенерированном xib-файле.Затем в коде я изменил:

var reuseableView = ReusableView.Create(item);
reuseableView.TranslatesAutoresizingMaskIntoConstraints = false;

exampleView.AddSubview(reuseableView);

на:

var reusableViewController = new ReuseableViewController(item);
var reuseableView = reusableViewController.View;
reuseableView.TranslatesAutoresizingMaskIntoConstraints = false;

exampleView.AddSubview(reuseableView);

Доступ к строго типизированному свойству View в ReuseableViewController гарантирует, что мой xib будет загружен и выводитсясвязано.В коде ReuseableViewController у меня есть следующее:

// Call to load from the XIB/NIB file
public ReuseableViewController(ExampleDependency dependency) : base("ReuseableViewController", NSBundle.MainBundle)
{
    _dependency = dependency;
}

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    if(_dependency != null)
    {
        TitleLabel.StringValue = _dependency.name;
        DateLabel.StringValue = _dependency.date;
        LocationLabel.StringValue = $"{_dependency.eventCity}, {_dependency.eventState}";
    }
}

Я не удовлетворен на 100% этим ответом, так как я считаю, что View Controller не должен быть необходим для повторного использования кода, поэтому еслиу кого-нибудь еще есть лучший ответ, пожалуйста, ответьте.

...