Як додати подання 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.