Objective C的 - 有一个视图控制器或多个视图之间翻转?(Objective c - Fl

2019-09-27 11:09发布

我建立一个位置的应用程序,显示用户身边的一些地方。
我有一个NearbyPlacesViewController与有两个按钮“列表”和“地图”段控制

如果“列表”用户按 - 我告诉他,他周围的地方列表中的表视图
如果用户按“图” - 视图翻转周围,我展示给用户在其上的地方作为引脚一个MapView。

在“清单”我也用一个UISearchBar和UISearchDisplayController搜索的tableView
在“地图”我也有MapView类之外的其他子视图

目前,我把所有的意见( UITableView, MKMapView, UISearchBar更多...)
和委托方法( UITableViewDelegate, UITableViewDataSource, MKMapViewDelegate, UISearchDisplayDelegate ,以及更多......)
NearbyPlacesViewController

当“地图”按钮,我隐藏所有的意见,相关的“列表”视图(的tableView,搜索栏...),我取消隐藏所有的意见,相关的“地图”查看用户按(MapView类,其他一些子视图...),然后我用UIView transitionWithView做他们之间翻转动画。

一切正常,但似乎有点乱,结果是一个大NearbyPlacesViewController了大量的代码和委托方法。

它是更好地与独立viewControllers办呢?
如果是这样,我怎么办呢? 我创建ListViewController和MapViewController中,并把它们放在一个NearbyViewController?
如何在它们之间共享的模式?

Answer 1:

只要你得到一个什么样的视图控制器遏制可能看起来像(iOS 5中)从某种意义上说,这是做这件事。 它由四个类的,容器视图控制器(其视图将具有用于两个子视图控制器之间进行切换的分段控制),两个随机子视图控制器和一个模型类,我们会在存储(其可以由被访问的数据两个子视图控制器)。

首先创建一个容器视图控制器与分段控制(我还加一个UIView基本上定义了子视图控制器的意见将被放置在框架,只是为了更容易地找出哪里把这一观点):

//  ContainerViewController.h

#import <UIKit/UIKit.h>

@interface ContainerViewController : UIViewController

@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
@property (weak, nonatomic) IBOutlet UIView *childView;

- (IBAction)changeChild:(id)sender;

@end

然后你实现它:

//  ContainerViewController.m

#import "ContainerViewController.h"
#import "FirstContainedViewController.h"
#import "SecondContainedViewController.h"
#import "MyModel.h"

@interface ContainerViewController ()
{
    FirstContainedViewController  *_controller0;
    SecondContainedViewController *_controller1;
    MyModel                       *_model;

    UIViewController __weak *_currentChildController; // let's keep track of the current 
}

@end

@implementation ContainerViewController

@synthesize segmentedControl = _segmentedControl;
@synthesize childView = _childView;

- (void)dealloc
{
    // let's release our child controllers

    _controller0 = nil;
    _controller1 = nil;

    // and release the model, too

    _model = nil;
}

// this is my own method to
// 1. add the child view controller to the view controller hierarchy;
// 2. do the appropriate notification (even though I don't use it, Apple says you should do this, so I will); and 
// 3. set the frame size to the appropriate size

- (void)addChildToThisContainerViewController:(UIViewController *)childController
{
    [self addChildViewController:childController];
    [childController didMoveToParentViewController:self];
    childController.view.frame = CGRectMake(0.0, 
                                            0.0, 
                                            self.childView.frame.size.width, 
                                            self.childView.frame.size.height);
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // let's create our model, our data

    _model = [[MyModel alloc] init];

    // set the segmented index to point to the first one

    [self.segmentedControl setSelectedSegmentIndex:0];

    // let's create our two controllers and provide each a pointer to our model

    _controller0 = [[FirstContainedViewController  alloc] initWithNibName:@"FirstContainedView"  bundle:nil];
    _controller0.model = _model;

    _controller1 = [[SecondContainedViewController alloc] initWithNibName:@"SecondContainedView" bundle:nil];
    _controller1.model = _model;

    // let's add them to the view controller hierarchy

    [self addChildToThisContainerViewController:_controller0];
    [self addChildToThisContainerViewController:_controller1];

    // let's add the currently selected controller as the "current child controller" and add it to our current view

    _currentChildController = [self.childViewControllers objectAtIndex:self.segmentedControl.selectedSegmentIndex];
    [self.childView addSubview:_currentChildController.view];
}

- (void)viewDidUnload
{
    [self setChildView:nil];
    [self setSegmentedControl:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (IBAction)segmentedControlValueChanged:(UISegmentedControl *)sender 
{
    UIViewController *oldChildController = _currentChildController;
    UIViewController *newChildController = [self.childViewControllers objectAtIndex:sender.selectedSegmentIndex];
    UIViewAnimationOptions options;

    // let's change the animation based upon which segmented control you select ... you may change this as fits your desired UI

    if (sender.selectedSegmentIndex == 0)
        options = UIViewAnimationOptionTransitionFlipFromLeft;
    else 
        options = UIViewAnimationOptionTransitionFlipFromRight;

    [self transitionFromViewController:oldChildController 
                      toViewController:newChildController
                              duration:0.5 
                               options:options 
                            animations:nil 
                            completion:nil];

    _currentChildController = newChildController;
}

@end

我的模型只是有两个数据元素,对象数组和字符串,但很明显,你可以做任何你想要的。 我将只显示标题(如实施细节是微乎其微的,无趣的):

//  MyModel.h

#import <Foundation/Foundation.h>

@interface MyModel : NSObject

@property (nonatomic, strong) NSMutableArray *listOfItems;
@property (nonatomic, strong) NSString *displayText;

- (MyModel *)init;

@end

和子视图控制器也同样简单:

//  FirstContainedViewController.h

#import <UIKit/UIKit.h>

@class MyModel;

@interface FirstContainedViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, weak) MyModel *model;

@end

和实现可能看起来像(这是一个简单的例子,但说明如何检索来自共享模型的信息):

//  FirstContainedViewController.m

#import "FirstContainedViewController.h"
#import "MyModel.h"

@implementation FirstContainedViewController

@synthesize model = _model;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

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

#pragma mark - tableview data source delegate methods

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.model.listOfItems count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"fcvc";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    cell.textLabel.text = [self.model.listOfItems objectAtIndex:indexPath.row];

    return cell;
}

@end

但愿这给你的,你怎么可能使用不同的视图控制器为你的两个观点从某种意义上说,如何在它们之间切换,让你的模型都可以访问。 这是一个相当简单的例子,但它的功能。 有一些优化,我可能会建议,但希望这是足以让你在正确的方向前进。



Answer 2:

一对夫妇的选项跳出我:

  1. 如果你使用一个UISegmentedControl ,你可以有两个UIView对象为你的两个屏幕(您可以在Interface Builder创建它们或以编程方式构建它们),然后你可以只隐藏/显示或addSubview / removeFromSuperview你它们之间跳转。 由于所有的数据都将通过您的单一视图控制器来管理,这是很容易的。 如果两个子视图得到非常复杂,不过,这种单一的视图控制器可能会变得相当毛。 但应该能正常运行。

  2. 如果你想单独视图控制器,你可能会追求的iOS 5的视图控制器遏制(见实现一个容器视图控制器在UIViewController中引用,或看WWDC 2011届102 ),虽然这是一个比较复杂的。 你可以存储你的数据作为由子控制器要么传给或参考容器视图控制器的性能。

  3. 如果你不结婚到分段控制界面,你可以只使用UITabBarController这是非常适合这种情况下(这是有效的一个选项的排列,但容器视图控制器,在这种情况下,标签栏控制器,是已经写了你)。 对于每个的两个视图中的一个视图控制器,并存储该数据要么在UITabBarController自定义类,一个单,一些持久性存储器(比如用户的默认值,核心数据,SQLite的)等。



Answer 3:

当与segmentedControl处理这是我如何在过去做到了。 您可能能够创建一个单独的控制器类来处理一切的基础模型,并清理出一些代码,但是这其实只是取决于你想多远,走了。



Answer 4:

想想ModelViewController。 如果他们是真正只有您之间切换视图,使用一个UIViewController中是合适的,这就是我通常做分段控制,因为它通常归结为各地电流控制器的视图切换。 控制器一定要处理IBAction为对分段的控制。

代表和数据源的意思是提取到一个单独的类时,它是有道理的,对你来说它。 我会考虑你正在使用的各种代表不同的类别,这将显著清理,同时也坚持贴近设计原则苹果打算。 你可以在自己的班级保持的UITableView委托和数据源一起,但除此之外,创建针对每个不同的委托一个独立的类会显著清理。



Answer 5:

独立的视图控制器可能是要走一个更合适的方法。 我喜欢他们。 也意味着你可以做出初步视图控制器的父母给了别人,并奠定了你有各种意见和subvuews父的意见添加您的孩子视图控制器为,当他们的需要。 也可以更容易地添加一些自定义动画或在稍后的日期继电器输出。



Answer 6:

在我看来,最好的办法是有三个视图控制器和它们之间创建模态塞格斯。 (我假设你使用故事板)。你必须有两个孩子(名单及地图)父视图控制器。

(1)在你的故事板(即具有ParentViewController,ListViewController&MapViewController中)从每个键子的VC创建模式Segue公司。 给他们标识符(showList&showMap将工作做好),并选择转型:水平翻转。

建立协议和代表:(我会告诉你如何做一个,然后就重复了)

(2a)中在ListViewController.h添加上述@interface:

@class ListViewController;

@protocol ListViewControllerDelegate
    - (void)listViewControllerDidFinish:(ListViewController *)controller;
@end

(2b)的添加委托作为一个属性:

@property (weak, nonatomic) id <ListViewControllerDelegate> delegate;

(3A)在ListViewController.m合成:

@synthesize delegate;

(3b)和在IBAction为按钮的方法来翻转回代表:

- (IBAction)flipBack:(id)sender
{
    [self.delegate ListViewControllerDidFinish:self];
}

(4)在添加ParentViewController.h在最高层#import "ListViewController.h"和@interface的端<ListViewControllerDelegate>

(5A)在ParentViewController.m添加方法,以符合协议:

- (void)listViewControllerFinish:(ListViewController *)controller
{
    [self dismissModalViewControllerAnimated:YES];
}

(5b)中然后将其设置为在prepareForSegue委托:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showList"]) {
        [[segue destinationViewController] setDelegate:self];
    }
}


文章来源: Objective c - Flip between views with one ViewController or more?