ios - UITableViewCell 链接到 PageViewController 中的特定页面

标签 ios objective-c uitableview

我是 iOS 编程的新手,遇到了一个我自己无法解决的问题。

我的应用程序的主要部分是可搜索的动物列表 (AnimalTableViewController)(此功能有效)。单击某个单元格后,您应该能够查看动物的图像。所有的动物图像都编译在 PagerViewController(CustomPagerViewController)中。

image of my storyboards can be found here

我需要做的是将动态表格单元格连接到特定的 View / Storyboard。我之前已经能够将单元格连接到图像 - 图像数组显示在单 View Controller 。这次我选择通过 PagerViewController 来完成,因为我需要滑动功能(与滑动相关的方法可以在 PagerViewController.m 中找到,它们都按预期工作)。

请你帮我解决这个问题,我还没有找到任何关于如何在 UITableView 和 PagerViewController 之间传递数据的教程或建议。

AnimalTableViewController.m

@implementation AnimalTableViewController

@synthesize allTableData;
@synthesize filteredTableData;
@synthesize searchBar;
@synthesize isFiltered;
@synthesize tableView;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super init];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    tableView.delegate = (id)self;
    tableView.dataSource = (id)self;

    searchBar.delegate = (id)self;

    allTableData = [[NSMutableArray alloc] initWithObjects:
                    [[Animal alloc] initWithName:@"Aardvark" andDescription:@"Aardvark"],
                    [[Animal alloc] initWithName:@"Alligator" andDescription:@"Alligator"],
                    [[Animal alloc] initWithName:@"Alpaca" andDescription:@"Alpaca"],
                    [[Animal alloc] initWithName:@"Ant" andDescription:@"Ant"],
                    [[Animal alloc] initWithName:@"Anteater" andDescription:@"Anteater"],
                    [[Animal alloc] initWithName:@"Armadillo" andDescription:@"Armadillo"],
                    [[Animal alloc] initWithName:@"Baboon" andDescription:@"Baboon"],
                    [[Animal alloc] initWithName:@"Badger" andDescription:@"Badger"],
                    [[Animal alloc] initWithName:@"Bat" andDescription:@"Bat"],
                    [[Animal alloc] initWithName:@"Bear" andDescription:@"Bear"],
                    [[Animal alloc] initWithName:@"Beaver" andDescription:@"Beaver"],
                    [[Animal alloc] initWithName:@"Bee" andDescription:@"Bee"],
                    [[Animal alloc] initWithName:@"Bison" andDescription:@"Bison"],
                    nil ];
}

- (void)viewDidUnload
{
    [self setSearchBar:nil];
    [super viewDidUnload];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    int rowCount;
    if(self.isFiltered)
        rowCount = filteredTableData.count;
    else
        rowCount = allTableData.count;

    return rowCount;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    Animal* animal;
    if(isFiltered)
        animal = [filteredTableData objectAtIndex:indexPath.row];
    else
        animal = [allTableData objectAtIndex:indexPath.row];

    cell.textLabel.text = animal.name;
//    cell.detailTextLabel.text = animal.description;

    return cell;
}

#pragma mark - Table view delegate

-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
    if(text.length == 0)
    {
        isFiltered = FALSE;
    }
    else
    {
        isFiltered = true;
        filteredTableData = [[NSMutableArray alloc] init];

        for (Animal* animal in allTableData)
        {
            NSRange nameRange = [animal.name rangeOfString:text options:NSCaseInsensitiveSearch];
            NSRange descriptionRange = [animal.description rangeOfString:text options:NSCaseInsensitiveSearch];
            if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
            {
                [filteredTableData addObject:animal];
            }
        }
    }

    [self.tableView reloadData];
}

@end

CustomPagerViewController.m

@interface CustomPagerViewController ()

@end

@implementation CustomPagerViewController

- (void)viewDidLoad
{
    // Do any additional setup after loading the view, typically from a nib.
    [super viewDidLoad];

    [self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"Aardvark"]];
    [self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"Alligator"]];
    [self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"Alpaca"]];
}

@end

PagerViewController.m

@interface PagerViewController ()
@property (assign) BOOL pageControlUsed;
@property (assign) NSUInteger page;
@property (assign) BOOL rotating;
- (void)loadScrollViewWithPage:(int)page;
@end

@implementation PagerViewController

@synthesize scrollView;
@synthesize pageControl;
@synthesize pageControlUsed = _pageControlUsed;
@synthesize page = _page;
@synthesize rotating = _rotating;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.scrollView setPagingEnabled:YES];
    [self.scrollView setScrollEnabled:YES];
    [self.scrollView setShowsHorizontalScrollIndicator:NO];
    [self.scrollView setShowsVerticalScrollIndicator:NO];
    [self.scrollView setDelegate:self];
}

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
    return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    [viewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    _rotating = YES;
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    [viewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.childViewControllers count], scrollView.frame.size.height);
    NSUInteger page = 0;
    for (viewController in self.childViewControllers) {
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        viewController.view.frame = frame;
        page++;
    }

    CGRect frame = self.scrollView.frame;
    frame.origin.x = frame.size.width * _page;
    frame.origin.y = 0;
    [self.scrollView scrollRectToVisible:frame animated:NO];

}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    _rotating = NO;
    UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    [viewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    for (NSUInteger i =0; i < [self.childViewControllers count]; i++) {
        [self loadScrollViewWithPage:i];
    }

    self.pageControl.currentPage = 0;
    _page = 0;
    [self.pageControl setNumberOfPages:[self.childViewControllers count]];

    UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    if (viewController.view.superview != nil) {
        [viewController viewWillAppear:animated];
    }

    self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.childViewControllers count], scrollView.frame.size.height);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    if ([self.childViewControllers count]) {
        UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
        if (viewController.view.superview != nil) {
            [viewController viewDidAppear:animated];
        }
    }
}

- (void)viewWillDisappear:(BOOL)animated {
    if ([self.childViewControllers count]) {
        UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
        if (viewController.view.superview != nil) {
            [viewController viewWillDisappear:animated];
        }
    }
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    if (viewController.view.superview != nil) {
        [viewController viewDidDisappear:animated];
    }
    [super viewDidDisappear:animated];
}

- (void)loadScrollViewWithPage:(int)page {
    if (page < 0)
        return;
    if (page >= [self.childViewControllers count])
        return;

    // replace the placeholder if necessary
    UIViewController *controller = [self.childViewControllers objectAtIndex:page];
    if (controller == nil) {
        return;
    }

    // add the controller's view to the scroll view
    if (controller.view.superview == nil) {
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [self.scrollView addSubview:controller.view];
    }
}

- (void)previousPage {
    if (_page - 1 > 0) {

        // update the scroll view to the appropriate page
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * (_page - 1);
        frame.origin.y = 0;

        UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
        UIViewController *newViewController = [self.childViewControllers objectAtIndex:_page - 1];
        [oldViewController viewWillDisappear:YES];
        [newViewController viewWillAppear:YES];

        [self.scrollView scrollRectToVisible:frame animated:YES];

        self.pageControl.currentPage = _page - 1;
        // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
        _pageControlUsed = YES;
    }
}

- (void)nextPage {
    if (_page + 1 > self.pageControl.numberOfPages) {

        // update the scroll view to the appropriate page
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * (_page + 1);
        frame.origin.y = 0;

        UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
        UIViewController *newViewController = [self.childViewControllers objectAtIndex:_page + 1];
        [oldViewController viewWillDisappear:YES];
        [newViewController viewWillAppear:YES];

        [self.scrollView scrollRectToVisible:frame animated:YES];

        self.pageControl.currentPage = _page + 1;
        // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
        _pageControlUsed = YES;
    }
}

- (IBAction)changePage:(id)sender {
    int page = ((UIPageControl *)sender).currentPage;

    // update the scroll view to the appropriate page
    CGRect frame = self.scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;

    UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
    UIViewController *newViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    [oldViewController viewWillDisappear:YES];
    [newViewController viewWillAppear:YES];

    [self.scrollView scrollRectToVisible:frame animated:YES];

    // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
    _pageControlUsed = YES;
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
    UIViewController *newViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
    [oldViewController viewDidDisappear:YES];
    [newViewController viewDidAppear:YES];

    _page = self.pageControl.currentPage;
}

#pragma mark -
#pragma mark UIScrollViewDelegate methods

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
    // which a scroll event generated from the user hitting the page control triggers updates from
    // the delegate method. We use a boolean to disable the delegate logic when the page control is used.
    if (_pageControlUsed || _rotating) {
        // do nothing - the scroll was initiated from the page control, not the user dragging
        return;
    }

    // Switch the indicator when more than 50% of the previous/next page is visible
    CGFloat pageWidth = self.scrollView.frame.size.width;
    int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    if (self.pageControl.currentPage != page) {
        UIViewController *oldViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
        UIViewController *newViewController = [self.childViewControllers objectAtIndex:page];
        [oldViewController viewWillDisappear:YES];
        [newViewController viewWillAppear:YES];
        self.pageControl.currentPage = page;
        [oldViewController viewDidDisappear:YES];
        [newViewController viewDidAppear:YES];
        _page = page;
    }
}

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    _pageControlUsed = NO;
}

// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _pageControlUsed = NO;
}

@end

最佳答案

为 segue 创建一个标识符(Interface Builder 中两个 View 之间的线)

enter image description here

然后在AnimalTableViewController中添加如下代码

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    Animal* animal;
    if(isFiltered)
        animal = [filteredTableData objectAtIndex:indexPath.row];
    else
        animal = [allTableData objectAtIndex:indexPath.row];

    [self performSegueWithIdentifier:@"DetailSegue" sender:animal];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"DetailSegue"]) {

        PagerViewController *detailVC = [segue destinationViewController];
        detailVC.currentAnimal = sender;
    }
}

然后在你的 PagerViewController.h 中创建

@property (strong, nonatomic) Animal *currentAnimal;

现在您可以通过 self.currentAnimal 访问 PagerViewController 中的动物

关于ios - UITableViewCell 链接到 PageViewController 中的特定页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13724323/

相关文章:

objective-c - 如果在变量前放置多个静态修饰符,这意味着什么?

ios - 设置导航后退按钮和导航 View 堆栈?

iphone - 从 MKUserTrackingModeFollowWithHeading 切换模式时如何始终保持 iOS 6 中的 MKMapView 朝北

iphone - UILabel 的 numberOfLines 在单元格中不起作用

iphone - 在 uitableview 中删除行

iphone - 无法呈现 modalViewController

objective-c - 计算网页加载到 UIWebView 所需的时间

ios - 动画结束时变慢

iphone - iPhone 的定位精度会超出职责范围吗?

ios - UITableViewController 内的 UINavigationBar