2015-05-13 2 views
2

Я пытаюсь подкласса UIPopoverController и дать ЭТО надлежащую ответственность за определение того, какой UIViewController (contentViewController) должен создавать и представлять, а не ужасно загромождать код вызова popover с этой ответственностью , Но я сталкиваюсь с несколькими проблемами.Что делать, если вы не можете вызвать [super init] вначале

Согласно документации Apple, никогда не будет веской причины делать что-либо перед первым вызовом.

if (self = [super init]) 

Так что я попробовал, что, думая, что я мог бы просто установить contentViewController свойство позже в методе, когда мой код изучил данные я прохожу в и принимает решение о том, какие UIViewController создавать и prsent, но называть [super init] удары с ошибкой, говорящей мне, что мне нужно вызвать другой инициализатор.

[super initWithContentViewController:...] 

Так что моя проблема проиллюстрирована ниже. Я не могу использовать первые строки своего пользовательского инициализатора, чтобы принять решение, а THEN - супер, когда вызов супер должен быть самым первым вызовом, и, по словам яблока, никогда не бывает веских причин не быть первым вызов.

initWithData:(MyDataObject*)data 
    // examine data object and determine what kind 
    // of UIViewController to create and present 
    // 
    // [super initWithContentViewController:myDecidedContentViewController 

Что делать? Спасибо.

ответ

2

От Apple documentation на UIPopoverController:

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

UIPopoverController не имеет никакого содержания его собственной, она нуждается в другой UIViewController, который визуализирует материал, вы на самом деле хотите представить. Любой подкласс UIViewController будет достаточным, если он не конфликтует с контроллером popover.

Например, вы можете использовать настраиваемый контроллер от Storyboard или XIB или программно созданный экземпляр UIViewController. Однако вы не ограничены этими двумя. Подкласс UIPopoverController не поможет, так как подкласс все еще нуждается в контроллере контента.

Теперь, подклассификация UIPopoverController и реализация логики для создания контроллера контента в этом классе является нарушением Single Responsibility Principle, поскольку вы будете смешивать обязанности для класса popover. В настоящее время у UIPopoverController есть одна и хорошая ответственность - отображать контроллеры представлений в popover, вы только обременяете это, если вы также несете ответственность за создание контроллеров контента.

Моей рекомендацией было бы создать класс MyPopoverFactory, который будет иметь методы, которые будут создавать как popover, так и его контроллер содержимого. Например:

- (UIPopoverController*)popoverForSomething 
+0

Это не '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '} Вы смешиваете обязанности, которые вы хотите, чтобы создавать контроллеры. Я бы предложил создать еще один класс, который создаст как popover, так и контроллер содержимого, обновит мой ответ с более подробной информацией. – Cristik

+0

Это похоже на разумную альтернативу, хотя это создаст намного больше кода. Теперь, когда я думаю об этом, похоже, что я нарушаю ответственность MVC (Massive View Controller), помещая решения данных внутри представления, а не Massive View Controller или некоторый класс, который он ссылается. –

+0

'Massive View Controller' - это интересный термин :) – Cristik

1

Я не знаю, помогает ли это, потому что я действительно не понимаю, какое решение вы должны принять. Но общий паттен, который вы можете использовать в такой ситуации (он похож на кластер классов), должен иметь другого создателя. (Вы можете сделать это с помощью -init…, но это неудобно. Если вам это нужно, дайте мне знать.)

+ (instancetype)myPopUpControllerForData:(id)data 
{ 
    // make the decision on data 
    Class contentViewControllerType; 
    contenViweControllerType = …; 

    // After that create the instance of the content view controller 
    contentViewController = [[ContentViewControllerType alloc] init…]; 

    // init… is the first message after alloction 
    self = [[self alloc] initWithContentViewController:contentViewController]; 

    return self; 
} 

документация только требует, чтобы -init… это первое сообщение выделенного экземпляра. Это не означает, что вы теряете свободу на запуск кода не, связанного с , что экземпляр.

+0

Хотя ваш ответ технически правильный и выполнимый, это было неправильное помещение, которое было ошибочным, и привело к вашему ответу. Я не должен пытаться поместить код решения данных внутри представлений ... это не так, как в коде кода MVC. Я все еще страдаю от индотонирования .NET и еще не полностью усвоил принципы MVC. –

+0

Это зависит от того, что такое 'data'. Если это общий тип данных, например 'NSArray',' NSSet' и т. Д., Я бы не отказался от вашей идеи. Эти типы представляют собой общий «фон» для стека MVC. Кроме того, вы принимаете решение для * контроллера * в зависимости от типа данных. Я бы не сказал, что это плохой дизайн. (И, конечно, жесткое устройство MVC может повредить. В какао есть несколько классов, которые не принадлежат к одному слою.) –

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