Note that there are some explanatory texts on larger screens.

plurals
  1. POBest Pattern for multiple Popovers in Storyboard
    text
    copied!<p>I am writing an iPad application which will have several buttons that when clicked open a popover to a tableview. The user will choose a value, and the popover will be dismissed and the button't title will change. </p> <p>I got this working with one Popover, and then wanted to add another. I want to write some good, clean reusable code. </p> <p>My big hangup is with delegates. How many should there be? Should each popover have its own.</p> <p>Root View Controller Header</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; #import "PopViewController1.h" #import "PopViewController2.h" @interface RootViewController : UIViewController &lt;PopViewControllerDelegate,UIPopoverControllerDelegate&gt; // Properties for accessing the popover and its viewcontroller (1) @property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover1; @property (strong, nonatomic) UIStoryboardPopoverSegue *pvcSegue1; @property (strong, nonatomic) PopViewController1 *pvc1; // Properties for accessing the popover and its viewcontroller (2) @property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover2; @property (strong, nonatomic) UIStoryboardPopoverSegue *pvcSegue2; @property (strong, nonatomic) PopViewController2 *pvc2; @end </code></pre> <p>Root View Controller Method</p> <pre><code>#import "RootViewController.h" @interface RootViewController () @end @implementation RootViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidUnload { [self setBtnOpenPopover1:nil]; [super viewDidUnload]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@"segPop1"]) { _pvcSegue1 = (UIStoryboardPopoverSegue *)segue; _pvc1 = [segue destinationViewController]; [_pvc1 setDelegate:self]; } else ([[segue identifier] isEqualToString:@"segPop2"]); { _pvcSegue2 = (UIStoryboardPopoverSegue *)segue; _pvc2 = [segue destinationViewController]; //[_pvc2 setDelegate:self]; } } // PopViewControllerDelegate callback function - (void)dismissPop:(NSString *)value { [_btnOpenPopover1 setTitle:value forState:UIControlStateNormal]; [[_pvcSegue1 popoverController] dismissPopoverAnimated: YES]; // dismiss the popover } @end </code></pre> <p>PopViewController1.h</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @protocol PopViewControllerDelegate; @interface PopViewController1 : UITableViewController @property (weak) id &lt;PopViewControllerDelegate&gt; delegate; @property (strong, nonatomic) NSString *strPassedValue; @property (nonatomic, strong) NSMutableArray *importantChoices; @end @protocol PopViewControllerDelegate &lt;NSObject&gt; @required - (void)dismissPop:(NSString *)value; @end </code></pre> <p>PopViewController1 Method</p> <pre><code>#import "PopViewController1.h" @interface PopViewController1 () @end @implementation PopViewController1 - (id)initWithCoder:(NSCoder *)aDecoder { //Popover Choices _importantChoices = [NSMutableArray array]; [_importantChoices addObject:@"Extremely Important"]; [_importantChoices addObject:@"Very Important"]; [_importantChoices addObject:@"Somewhat Important"]; [_importantChoices addObject:@"Not Very Important"]; [_importantChoices addObject:@"Not At All Important"]; self.clearsSelectionOnViewWillAppear = NO; NSInteger rowsCount = [_importantChoices count]; NSInteger singleRowHeight = [self.tableView.delegate tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; NSInteger totalRowsHeight = rowsCount * singleRowHeight; //Calculate how wide the view should be by finding how //wide each string is expected to be CGFloat largestLabelWidth = 0; for (NSString *colorName in _importantChoices) { //Checks size of text using the default font for UITableViewCell's textLabel. CGSize labelSize = [colorName sizeWithFont:[UIFont boldSystemFontOfSize:20.0f]]; if (labelSize.width &gt; largestLabelWidth) { largestLabelWidth = labelSize.width; } } //Add a little padding to the width CGFloat popoverWidth = largestLabelWidth + 100; //Set the property to tell the popover container how big this view will be. self.contentSizeForViewInPopover = CGSizeMake(popoverWidth, totalRowsHeight); return self; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Uncomment the following line to preserve selection between presentations. //self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload]; } - (void)viewWillAppear: (BOOL)animated { } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [_importantChoices count];} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.textLabel.text = [_importantChoices objectAtIndex:indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { _strPassedValue = [_importantChoices objectAtIndex:indexPath.row]; [_delegate dismissPop:_strPassedValue]; } @end </code></pre> <p>PopViewController2 Header</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @protocol PopViewControllerDelegate; @interface PopViewController2 : UITableViewController @property (weak) id &lt;PopViewControllerDelegate&gt; delegate; @property (strong, nonatomic) NSString *strPassedValue2; @property (nonatomic, strong) NSMutableArray *importantChoices2; @end @protocol PopViewControllerDelegate &lt;NSObject&gt; @required - (void)dismissPop2:(NSString *)value; @end </code></pre> <p>PopViewController2 Method</p> <h1>import "PopViewController2.h"</h1> <p>@interface PopViewController2 ()</p> <p>@end</p> <p>@implementation PopViewController2</p> <pre><code>- (id)initWithCoder:(NSCoder *)aDecoder { //Popover Choices _importantChoices = [NSMutableArray array]; [_importantChoices addObject:@"Extremely Important"]; [_importantChoices addObject:@"Very Important"]; [_importantChoices addObject:@"Somewhat Important"]; [_importantChoices addObject:@"Not Very Important"]; [_importantChoices addObject:@"Not At All Important"]; self.clearsSelectionOnViewWillAppear = NO; NSInteger rowsCount = [_importantChoices count]; NSInteger singleRowHeight = [self.tableView.delegate tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; NSInteger totalRowsHeight = rowsCount * singleRowHeight; //Calculate how wide the view should be by finding how //wide each string is expected to be CGFloat largestLabelWidth = 0; for (NSString *colorName in _importantChoices) { //Checks size of text using the default font for UITableViewCell's textLabel. CGSize labelSize = [colorName sizeWithFont:[UIFont boldSystemFontOfSize:20.0f]]; if (labelSize.width &gt; largestLabelWidth) { largestLabelWidth = labelSize.width; } } //Add a little padding to the width CGFloat popoverWidth = largestLabelWidth + 100; //Set the property to tell the popover container how big this view will be. self.contentSizeForViewInPopover = CGSizeMake(popoverWidth, totalRowsHeight); return self; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Uncomment the following line to preserve selection between presentations. //self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload]; } - (void)viewWillAppear: (BOOL)animated { } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [_importantChoices count];} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.textLabel.text = [_importantChoices objectAtIndex:indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { _strPassedValue = [_importantChoices objectAtIndex:indexPath.row]; [_delegate dismissPop:_strPassedValue]; } @end </code></pre> <p>Any help or suggestions would be greatly appreciated!!!</p> <p>Bryan</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload