it-swarm.com.ru

Как получить предыдущий viewcontroller, который выдвинул мое текущее представление

На главной странице моего приложения есть UIButtons, btnIncome и btnExpense. При нажатии на эти кнопки соответственно нажимаются IncomeVC и ExpenseVC, которые представляют собой два UIViewControllers с добавлением UITabBar через xib. TabBar имеет 4 элемента. Выбор на каждой вкладке добавляет те же четыре контроллера представления (которые содержат UITableViews) в качестве подпредставления IncomeVC и ExpenseVC, как, например, для DailyVC, WeeklyVC, MonthlyVC, YearlyVC. (Т. Е. Для Income, ежедневно, еженедельно и т.д. Расход) (я так и сделал, потому что IncomeVC и ExpenseVC имеют UIButton и UIView, которые являются общими для всех вкладок). 

Таким образом, проблема в том, что, если щелкнуть btnIncome, я должен заполнить эти табличные представления массивами, связанными с доходом, и наоборот для расходов. Как узнать, из какого viewController я выбрал разные вкладки (мне нужно получить его из 4 представлений, которые я добавил как подпредставление IncomeVC и ExpenseVC). Должен ли я сделать 8 различных просмотров 4 каждый для доходов и расходов? Спасибо.

32
Midas

Если причина необходимости доступа к предыдущему контроллеру представления заключается в том, чтобы знать, какие данные нужно получить, я бы посоветовал вам вместо этого предоставить новому контроллеру представления данные, прежде чем помещать их в стек. Или, по крайней мере, достаточно данных, чтобы контроллер представления знал, как получить правильные данные, например, перечисление или константа или что-то. 

Это можно сделать с помощью пользовательского инициализатора или свойства . Посмотрите на этот пост в блоге для примера: «Передача данных между контроллерами представления»

Если вы используете раскадровку, вы можете использовать prepareForSegue:sender для передачи правильных данных. Хороший учебник по этому вопросу можно найти здесь: Начало раскадровки в iOS 5, часть 2

7
Vegar

Вы можете получить предыдущий viewController, как следующий код,

NSLog(@"%@",[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2]);

Это отобразит предыдущее имя viewController ...

35
Venk

В Свифт 3 ,

if let navController = self.navigationController, navController.viewControllers.count >= 2 {
     let viewController = navController.viewControllers[navController.viewControllers.count - 2]
}
25
Venk

В Свифт :

let n: Int! = self.navigationController?.viewControllers?.count
let myUIViewController = self.navigationController?.viewControllers[n-2] as! UIViewController
20
King-Wizard

Swift 3

Вот список предыдущих ответов, которые можно поместить в расширение:

extension UIViewController{
   var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers, controllersOnNavStack.count >= 2 {
            let n = controllersOnNavStack.count
            return controllersOnNavStack[n - 2]
        }
        return nil
    }
}

Правка:

При получении previousViewController данного контроллера представления, назовите его VC1, в viewWillDisappear VC1 уже извлечен из стека контроллера навигации. Таким образом, в этом сценарии приведенный выше код не заканчивает выборкой контроллера View непосредственно над VC1 (назовите его VC2), а контроллером View выше VC2 (если он существует).

Чтобы избежать этой проблемы, я просто проверяю, находится ли VC1 в стеке, когда запрашивается previousViewController. Вот обновленный код:

extension UIViewController{
    var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers{
            let n = controllersOnNavStack.count
            //if self is still on Navigation stack
            if controllersOnNavStack.last === self, n > 1{
                return controllersOnNavStack[n - 2]
            }else if n > 0{
                return controllersOnNavStack[n - 1]
            }
        }
        return nil
    }
}

В этом коде предполагается, что контроллер представления, которому вы отправляете сообщение previousViewController, будет либо в верхней части стека навигации, либо вообще не будет.

7
J.beenie
UIViewController *previousViewController = [[[self navigationController]viewControllers] objectAtIndex:([viewControllers indexOfObject:self]-1)];

Где self будет текущим представлением контроллера.

4
Zaraki

Swift 4.1, 4.2

 let allPreviousViewC = currentViewController.navigationController?.viewControllers // will give array of all pushed VC
// Can use if condition to check array count and then put below code inside that condition
    for viewC in allPreviousViewC! {
           print("ViewC is \(viewC)")
      }
1
GSK

Стриж

extension UINavigationController {
    func getPreviousViewController() -> UIViewController? {
        let count = viewControllers.count
        guard count > 1 else { return nil }
        return viewControllers[count - 2]
    }
}
1
dimpiax

Посмотрите этот пост: Как определить предыдущий контроллер представления в стеке навигации Тони прав, вы можете получить предыдущий VC из массива viewControllers, но по индексу n-2.

0
CharlieReed

Вы можете, конечно, повторно использовать контроллеры представления. Я бы предложил вместо нажатия UIViewController (который содержит UITabBar, добавленный из IB), когда кнопка нажата, вы можете нажать UITabBarController, который содержит 4 контроллера просмотра (ежедневно, еженедельно, ежемесячно и ежегодно). 

У вашего UITabBarController может быть свойство enum (Income and Expense), и его можно назначить, когда вы нажимаете этот UITabBarController на основе нажатой кнопки. Оттуда вы можете назначить другое свойство enum (Income and Expense) для 4 UIViewControllers, чтобы показать правильный тип данных в каждом контроллере представления.

0
Valent Richie