Як додати подання UIViewController як підпрогляд


75

Зверніть увагу, що Google перевіряє, що цей контроль якості вже застарів на шість років !

Як зазначають Мікі та інші, це тепер робиться щодня за допомогою контейнерів в iOS.


У мене є ViewController, який керує багатьма підпрограмами. Коли я натискаю одну з кнопок, я ініціалізую інший контролер подання і показую його вигляд як підпрогляд цього подання. Однак підпрогляд перевищує межі кадру для перегляду, і фактично заповнює весь екран.

Що може бути не так? Я припускаю, що проблема полягає в тому, що вид UIViewController має кадр (0,0320,460) і, отже, заповнює весь екран (хоча він отримує події дотику лише при дотику в межах рамки підпрогляду). Як я можу змінити розмір кадру, щоб він містився як підпрогляд.

Коротше кажучи, мені потрібна допомога, щоб додати подання контролера подання як підпрогляд до подання іншого контролера подання.

Дякую!


1
Я б рекомендував проти цього. Я зробив це для свого першого додатку для iPhone, і це виявилося величезним химерним безладом, не кажучи вже про те, що це зламало багато всього, що я намагався зробити з Interface Builder. У документах 3.0 вони конкретно кажуть - 1 контролер перегляду на екран. Ви повинні це зробити!
bpapa

Так, навіть я читав про це, але проблема полягає в тому, що якщо я покладу все це в 1 viewcontroller, це цілий ряд коду в 1, і існує безліч IBOutlets, дій і таблиць. Отже, для ясності та модульності я намагався мати 2 окремі контролери перегляду, причому другий лише забезпечував перегляд основного контролера перегляду та обробляв власні події. Таким чином, головний контролер перегляду стає дещо чистішим. Що я маю робити замість цього. Чи повинен я мати кілька контролерів перегляду з контролером навігації або 1 величезний контролер перегляду.
сперма

Погляньте на цей посібник . Хоча це працює лише частково
Casebash

Відповіді:


86

Починаючи з iOS 5 , Apple тепер дозволяє створювати власні контейнери з метою додавання UIViewController до іншого UIViewController, особливо за допомогою таких методів, як addChildViewController, тому дійсно можна вкладати UIViewControllers

РЕДАГУВАТИ: включаючи резюме на місці, щоб уникнути обриву посилань

Я цитую:

iOS пропонує безліч стандартних контейнерів, які допоможуть вам упорядкувати ваші програми. Однак іноді потрібно створити власний робочий процес, який не збігається з тим, який надається будь-яким із системних контейнерів. Можливо, у вашому баченні ваш додаток потребує певної організації контролерів дочірнього перегляду зі спеціалізованими жестами навігації або переходами анімації між ними. Для цього ви впроваджуєте спеціальний контейнер - Скажіть мені більше ...

... і:

При створенні контейнера, ви створюєте явний батько-нащадок між контейнером, батьком та іншими контролерами зору, його дітьми - Розкажіть мені більше

Зразок (люб'язно надано документами Apple) Додавання подання іншого контролера подання до ієрархії подання контейнера

- (void) displayContentController: (UIViewController*) content
{
   [self addChildViewController:content];                 
   content.view.frame = [self frameForContentController]; 
   [self.view addSubview:self.currentClientView];
   [content didMoveToParentViewController:self];          
}

2
Додав коментар у верхній частині моєї відповіді на це.
Стівен Фішер

Ви впевнені, що це iOS 5? У мене виникають збої з iOS 5, але в iOS 6 це працює нормально.
Стівен Фішер

iOS 5, ми використовуємо його в нашому додатку
MickyD

Дякую Міккі. Виявляється, це лише вбудована розкадровка, яка не підтримується в iOS 5.
Стівен Фішер

3
Яка роль currentClientView? Я взагалі не можу зрозуміти це в документації.
Юліан Онофрей 02.03.15

41

Завдяки цим хлопцям я зробив це http://highoncoding.com/Articles/848_Creating_iPad_Dashboard_Using_UIViewController_Containment.aspx

Додайте UIView, підключіть його до заголовка:

@property (weak, nonatomic) IBOutlet UIView *addViewToAddPlot;

У - (void) viewDidLoad зробіть це:

ViewControllerToAdd *nonSystemsController = [[ViewControllerToAdd alloc] initWithNibName:@"ViewControllerToAdd" bundle:nil];
    nonSystemsController.view.frame = self.addViewToAddPlot.bounds;
    [self.addViewToAddPlot addSubview:nonSystemsController.view];
    [self addChildViewController:nonSystemsController];
    [nonSystemsController didMoveToParentViewController:self];

Насолоджуйтесь


3
У документації зазначено, що didMoveToParentViewController слід викликати після addChildViewController, а не раніше.
Аарон

Дякую ... чудове рішення!
jalopezsuarez

26

Ця відповідь правильна для старих версій iOS, але зараз застаріла. Ви повинні використати відповідь Мікі Дункана, яка охоплює спеціальні контейнери.

Не роби цього! НамірUIViewController є керувати всім екраном. Це просто не підходить для цього, і насправді не додає нічого, що вам потрібно.

Все, що вам потрібно, - це об’єкт, якому належить ваш власний вигляд. Просто використовуйте підкласUIView себе, щоб його можна було додати до вашої ієрархії вікон, а управління пам’яттю було повністю автоматичним.

Вкажіть власника підпункту NIB на спеціальний підклас UIView. Додайте contentViewрозетку до цього користувацького підкласу та направте його на вигляд у перо. У спеціальному підкласі виконайте щось подібне:

- (id)initWithFrame: (CGRect)inFrame;
{
    if ( (self = [super initWithFrame: inFrame]) ) {
        [[NSBundle mainBundle] loadNibNamed: @"NibNameHere"
                                      owner: self
                                    options: nil];
        contentView.size = inFrame.size;
        // do extra loading here
        [self addSubview: contentView];
    }
    return self;
}

- (void)dealloc;
{
    self.contentView = nil;
    // additional release here
    [super dealloc];
}

(Я припускаю, що тут ви використовуєте initWithFrame:для побудови підпрогляду.)


2
хоча на той час це досить гарна відповідь, це, можливо, застаріла філософія з iOS 5. Дивіться мою відповідь нижче
MickyD

1
Дійсно, це було написано багато років тому. Я ще не використовував спеціальні контейнери, але це, здається, правильний спосіб вирішити це.
Стівен Фішер,

Дякую за підключення до моєї відповіді Стівен :)
MickyD

17

Мені здається, що всі ці відповіді трохи неповні, тому ось правильний спосіб додати подання viewController як підпрогляд подання іншого viewController:

    [self addChildViewController:viewControllerToAdd];
    [self.view addSubview:viewControllerToAdd.view];
    [viewControllerToAdd didMoveToParentViewController:self];

Якщо ви хочете, ви можете скопіювати це у свій код як фрагмент. Отож, схоже, не розуміє форматування заміни коду, але вони будуть відображатися чисто в Xcode:

    [self addChildViewController:<#viewControllerToAdd#>];
    [self.view addSubview:<#viewControllerToAdd#>.view];
    [<#viewControllerToAdd#> didMoveToParentViewController:self];

willMove викликається автоматично w / addChild. Дякую @iOSSergey

Коли ваш користувацький контейнер викликає метод addChildViewController:, він автоматично викликає метод willMoveToParentViewController: метод контролера перегляду, який слід додати як дочірній матеріал перед його додаванням.


Коли ваш користувацький контейнер викликає метод addChildViewController:, він автоматично викликає метод willMoveToParentViewController: метод контролера перегляду, який слід додати як дочірній матеріал перед його додаванням.
iOSergey

@iOSergey у вас є посилання на це? Хотілося б оновити відповідь, щоб вона була більш правильною.
Логан

Я насправді завжди використовував willMoveToParent і вручну, але коли випадково прочитав посилання на яблуко на цю функцію, був здивований :) developer.apple.com/library/ios/documentation/UIKit/Reference/… :
iOSergey

@iOSergey - вибачте, можливо, я густую, але я там цього не бачу :) Розум вказує мені трохи конкретніше! Ви не самі завжди телефонуєте, і я хотів би мати хороший довідник, коли люди неминуче кажуть мені, щоб я повернув його назад! Знову дякую!
Логан

Шукайте "willMoveToParentViewController" на веб-сайті, на який я зв’язав, витратьте посилання "willMoveToParentViewController" і під заголовком обговорення останній абзац :) Я розмістив повне посилання, але з певних причин його перенаправляючи вгору.
iOSergey


1

Змініть розмір кадру viewcontroller.view.frameта додайте до підпрогляду.[viewcontrollerparent.view addSubview:viewcontroller.view]


Я спробував. Це не працює. Чи слід щось робити у конструкторі інтерфейсів.
сперма

0

Ви повинні встановити властивості меж, щоб відповідати цьому кадру. кадр його властивостей супервигляду, а межі обмежують кадр у самій системі координат вигляду.


0

Ви можете використовувати PopupController для того самого пакета SDK, який показує UIViewController як підзапис. Ви можете перевірити PopupController

Ось зразок коду для того самого

popup = PopupController
        .create(self.navigationController!)
        .customize(
            [
                .layout(.center),
                .animation(.fadeIn),
                .backgroundStyle(.blackFilter(alpha: 0.8)),
                .dismissWhenTaps(true),
                .scrollable(true)
            ]
        )
        .didShowHandler { popup in
        }
        .didCloseHandler { popup in
    }
    let container = MTMPlayerAndCardSelectionVC.instance()
    container.closeHandler = {() in
        self.popup.dismiss()
    }

    popup.show(container)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.