Я прочитал много других тем по этому вопросу и в документации Apple, но еще не нашел решения для своей конкретной проблемы.
Мое приложение использует UITabBarController
в качестве rootViewController
, а на одной из вкладок у меня есть UISegmentedControl
в navigationBar
для переключения между тремя дочерними UITableViewController
.
(В реальном приложении два дочерних VC являются пользовательскими UIViewController
, я просто использую три UITableViewController
для примера приложения).
Настройка segmentedControl и переключение работают нормально. Что идет не так, так это то, что правильно отображается только первый UITableViewController
. Для второго и третьего часть первой ячейки скрыта под navigationBar
. Когда я щелкаю по всем трем, первый все еще в порядке.
Я сделал небольшой пример приложения, чтобы показать, что происходит, используя очень яркие цвета для демонстрационных целей: https://www.dropbox.com/s/7pfutvn5jba6rva/SegmentedControlVC.zip?dl=0
Вот также код (я не использую раскадровки):
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
FirstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *firstNavigationController = [[UINavigationController alloc] initWithRootViewController: fvc];
SecondViewController *svc = [[SecondViewController alloc] init];
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController: svc];
// Initialize tab bar controller, add tabs controllers
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = @[firstNavigationController, secondNavigationController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
// FirstViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @"One";
self.view.backgroundColor = [UIColor orangeColor];
UITableViewController *vc1 = [[UITableViewController alloc] init];
UITableViewController *vc2 = [[UITableViewController alloc] init];
UITableViewController *vc3 = [[UITableViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
vc2.view.backgroundColor = [UIColor blueColor];
vc3.view.backgroundColor = [UIColor greenColor];
self.viewControllers = @[vc1, vc2, vc3];
self.segmentTitles = @[@"Red", @"Blue", @"Green"];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems: self.segmentTitles];
[self.segmentedControl addTarget: self
action: @selector(segmentClicked:)
forControlEvents: UIControlEventValueChanged];
self.navigationItem.titleView = self.segmentedControl;
self.segmentedControl.selectedSegmentIndex = 0;
// set the first child vc:
UIViewController *vc = self.viewControllers[0];
[self addChildViewController: vc];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
self.currentVC = vc;
}
- (void)segmentClicked:(id)sender
{
if (sender == self.segmentedControl)
{
NSUInteger index = self.segmentedControl.selectedSegmentIndex;
[self loadViewController: self.viewControllers[index]];
}
}
- (void)loadViewController:(UIViewController *)vc
{
[self addChildViewController: vc];
[self transitionFromViewController: self.currentVC
toViewController: vc
duration: 1.0
options: UIViewAnimationOptionTransitionFlipFromBottom
animations: ^{
[self.currentVC.view removeFromSuperview];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
} completion: ^(BOOL finished) {
[vc didMoveToParentViewController: self];
[self.currentVC removeFromParentViewController];
self.currentVC = vc;
}
];
}
Поэтому, очевидно, мой вопрос: почему это происходит и что я могу сделать, чтобы это исправить?
Редактировать: добавление скриншотов.
РЕДАКТИРОВАТЬ: Основываясь на ответе ниже, я изменил код в блоке анимации на:
[self.currentVC.view removeFromSuperview];
if ([vc.view isKindOfClass: [UIScrollView class]])
{
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0);
[UIView performWithoutAnimation: ^{
vc.view.frame = self.view.bounds;
((UIScrollView *)vc.view).contentInset = edgeInsets;
((UIScrollView *)vc.view).scrollIndicatorInsets = edgeInsets;
}];
}
else
{
vc.view.frame = self.view.bounds;
}
[self.view addSubview: vc.view];
Теперь это работает. Я также собираюсь попробовать это с пользовательским UIViewController
.
topLayoutGuide.length
контроллера. - person Leo Natan   schedule 01.08.2015[UIView performWithoutAnimation:]
для установки вставок без анимации. - person Leo Natan   schedule 01.08.2015topLayoutGuide.length
, тоviewDidLayoutSubviews
вызывается только в первый раз (для красного ВК), и моя проблема возвращается. - person koen   schedule 01.08.2015viewDidLayoutSubviews
не следует использовать для установки вставок последующих представлений, потому что его действительно не следует вызывать позже. А вы говорите, установка их вloadViewController:
не работает, что странно. Если вы установили их только вloadViewController:
и видите плохо, что произойдет, если вы попытаетесь прокрутить пальцем на плохом виде таблицы? Позволяет ли он прокручивать ячейку в полноэкранном режиме? Если это так, вам также нужно установитьcontentOffset
равным{0, contentInset.top}
. - person Leo Natan   schedule 01.08.2015topLayoutGuide.length
работает. Мне пришлось еще немного подправить код в блоке анимации, чтобы заставить его работать, см. мое редактирование выше. - person koen   schedule 01.08.2015