I have a split view controller for iPad with a drill-down table on the left. I am able to populate the tables with a drill-down without issue but I cannot seem to get the item I clicked within the UITableView on the left side to show up in detailDescriptionLabel on the right side.
I have the following code in my ProductViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Row clicked: %i", indexPath.row);
if (_delegate != nil) {
Product *product = (Product *) [_products objectAtIndex:indexPath.row];
[_delegate productSelectionChanged:product];
}
DetailedVC *detailView = [[DetailedVC alloc] initWithNibName:#"DetailedVC" bundle:[NSBundle mainBundle]];
NSLog(#"User clicked on: %#", [NSString stringWithFormat:#"%d",indexPath.row]);
detailView.detailDescriptionLabel.text = [NSString stringWithFormat:#"%d",indexPath.row];
[self.navigationController pushViewController:detailView animated:YES];
}
What happens here is I push the DetailedVC into the left side where my table view is and what I really want to do is see the row clicked updated in my detailed view on the right. I am able to see in the Log window that I clicked on a certain index so I know I am capturing the click event and getting a value.
Inside my DetailedVC.m I have the following code to update this label.
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void) configureView {
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
NSLog(#"Item: %#", [self.detailItem description]);
}
}
If I edit the viewDidLoad I get a (null) for the [self.detailItem description]
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Detail description label: %#", [self.detailItem description]);
}
ProductViewController.h
#interface ProductViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
NSMutableArray *_products;
UITableView *_productsTableView;
id<ProductSelectionDelegate> _delegate;
}
#property (nonatomic, strong) IBOutlet UITableView *productsTableView;
#property (nonatomic, retain) NSMutableArray *products;
#property (nonatomic, assign) id<ProductSelectionDelegate> delegate;
#end
AppDelegate.h
#class ProductViewController;
#class DetailedVC;
#interface TabAndSplitAppAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
ProductViewController *_productViewController;
DetailedVC *_detailedViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, retain) IBOutlet ProductViewController *productViewController;
#property (nonatomic, retain) IBOutlet DetailedVC *detailedViewController;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSMutableArray *products = [NSMutableArray array];
[products addObject:[[Product alloc] initWithName:#"Product 1 Name" desc:#"Product 1 Description"]];
_detailedViewController.product = [products objectAtIndex:0];
// Override point for customization after app launch.
//create split view controller
RootVC *rvc=[[RootVC alloc] init];
rvc.title=#"Root VC";
DetailedVC *dvc=[[DetailedVC alloc] init];
dvc.title=#"Detailed VC";
_productViewController.delegate = _detailedViewController;
MySplitViewController *msc = [[MySplitViewController alloc] initwithLeftVC:rvc rightVC:dvc];
msc.title=#"First";
//create a temporary VC to show in second tab
SecondViewController *vc2 = [[SecondViewController alloc] init];
vc2.title=#"Second";
//make an array containing these two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:msc,vc2,nil];
[tabBarController setViewControllers:viewControllers];
tabBarController.view.backgroundColor=[UIColor blackColor];
for(UITabBarItem*t in tabBarController.tabBar.items)
{
t.image=[UIImage imageNamed:#"icon.png"];
t.badgeValue=[NSString stringWithFormat:#"%d",([tabBarController.tabBar.items indexOfObject:t]+1)];
}
//the views are retained their new owners, so we can release
[rvc release];
[dvc release];
[msc release];
[vc2 release];
// Add the tab bar controller's current view as a subview of the window
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
return YES;
}
MySplitViewController.h
#import <UIKit/UIKit.h>
#interface MySplitViewController : UIViewController
{
UINavigationController *leftController;
UINavigationController *rightController;
}
#property (nonatomic, retain) UINavigationController *leftController;
#property (nonatomic, retain) UINavigationController *rightController;
- (void)layoutViews:(UIInterfaceOrientation)orientation initialVerticalOffset:(float)offset;
- (MySplitViewController*) initwithLeftVC:(UIViewController*)leftvc rightVC:(UIViewController*)rightvc;
#end
MySplitViewController.m
- (MySplitViewController*) initwithLeftVC:(UIViewController*)leftvc rightVC:(UIViewController*)rightvc
{
if(self=[super init])
{
UINavigationController *lnc=[[UINavigationController alloc] initWithRootViewController:leftvc];
lnc.navigationBarHidden=NO;
self.leftController=lnc;
[lnc release];
UINavigationController *rnc=[[UINavigationController alloc] initWithRootViewController:rightvc];
rnc.navigationBarHidden=NO;
self.rightController=rnc;
[rnc release];
}
return self;
}
Product.h
#import <Foundation/Foundation.h>
#interface Product : NSObject {
NSString *_productID;
NSString *_productDescription;
}
#property (nonatomic, copy) NSString *productID;
#property (nonatomic, copy) NSString *productDescription;
- (Product *)initWithName:(NSString *)productID desc:(NSString *)productDescription;
#end
Product.m
#import "Product.h"
#implementation Product
#synthesize productID = _productID;
#synthesize productDescription = _productDescription;
- (Product *)initWithName:(NSString *)productID desc:(NSString *)productDescription {
if ((self = [super init])) {
self.productID = productID;
self.productDescription = productDescription;
}
return self;
}
#end
Ok, please try this in ProductViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Row clicked: %i", indexPath.row);
Product *product = (Product *) [_products objectAtIndex:indexPath.row];
NSLog(#"Product: %#", product);
TabAndSplitAppAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"appDelegate: %#", appDelegate);
UITabBarController *tbc = appDelegate.tabBarController;
NSLog(#"tbc: %#", tbc);
MySplitViewController *msvc = tbc.selectedViewController;
NSLog(#"msvc: %#", msvc);
UINavigationController *rnc = msvc.rightController;
NSLog(#"rnc: %#", rnc);
DetailedVC *dvc = rnc.topViewController;
NSLog(#"dvc: %#", dvc);
dvc.detailDescriptionLabel.text = #"We found our DetailedVC";
[dvc productSelectionChanged:product];
}
This code is not an example of how you should structure your program properly. This was just to help me (and you) understand your view controller hierarchy.
The initial idea of notifying a delegate when a product is selected is spot on, it just didn't work in your case because the objects weren't wired up properly. You should try to do that though. In the code you posted, I don't see a location where both the ProductViewControllerand the DetailedVC are both directly visible so that you could just say
productViewControllerInstance.delegate = detailedVCinstance;
The nearest to that is in AppDelegate where you have the RootVC instance rvcthat presumably eventually will create the ProductViewController and the dvc. Maybe you could give the dvcto the rvcso that it can set it as the ProductViewController's delegate when it's created. Good luck!
Related
After hours if trying to solve this error i decided to reach out for
help. I Keep on getting the same error :
"Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '***
-[__NSCFConstantString stringByAppendingString:]: nil argument'"
#import <UIKit/UIKit.h>
#interface BrowseTableViewController : UITableViewController
#property (strong) NSMutableArray *emp; //An array to store all the information of clicked entries
#end
#import <CoreData/CoreData.h>
#import "BrowseClickViewController.h"
#import "ItemTableViewCell.h"
#interface BrowseTableViewController ()<UITableViewDelegate, UITableViewDataSource>
#end
#implementation BrowseTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self.tableView registerNib:[UINib nibWithNibName:#"ItemTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"Cell1"];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
[_emp removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Employee"];
self.emp = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy]; // Obtaining all the entries of persistance store to show in Table view
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.emp.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell1";
ItemTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *empp = [self.emp objectAtIndex:indexPath.row]; //obtaining the informatio of selected row in empp object
[cell.itemName setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"name"]]];
[cell.quantityLabel setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"quantity"]]];
[cell.shopLabel setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"store"]]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BrowseClickViewController *initViewController = [storyBoard instantiateViewControllerWithIdentifier:#"Click"];
[self.navigationController presentViewController:initViewController animated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{ //Segue which is called when user selects any row, and this segue modifies the value of emp object of BrowseClickViewController with the clicked row details.
if ([segue.identifier isEqualToString:#"recordClicked"]){
NSManagedObject *selectedEmp = [self.emp objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
BrowseClickViewController *destViewController = segue.destinationViewController;
destViewController.emp = selectedEmp;
}
}
#end
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface BrowseClickViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *scroller;
#property (weak, nonatomic) IBOutlet UILabel *barcodeLabel;
#property (weak, nonatomic) IBOutlet UILabel *categoryLabel;
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
#property (weak, nonatomic) IBOutlet UILabel *priceLabel;
#property (weak, nonatomic) IBOutlet UILabel *quantityLabel;
#property (weak, nonatomic) IBOutlet UILabel *storeLabel;
#property (weak, nonatomic) IBOutlet UIImageView *imagePicture;
#property (strong) NSManagedObject *emp;
#property (weak, nonatomic) NSString *picLabel;
#end
#import "BrowseClickViewController.h"
#import "BrowseTableViewController.h"
#import <CoreData/CoreData.h>
#import "ItemTableViewCell.h"
#interface BrowseClickViewController ()
#end
#implementation BrowseClickViewController
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidLoad {
[super viewDidLoad];
_nameLabel.text=[#"Name:" stringByAppendingString:[self.emp valueForKey:#"name"]];
_barcodeLabel.text=[#"Barcode:" stringByAppendingString:[self.emp valueForKey:#"barcode"]];
_categoryLabel.text=[#"Category:" stringByAppendingString:[self.emp valueForKey:#"category"]];
_priceLabel.text=[#"Price:"stringByAppendingString:[self.emp valueForKey:#"price"]];
_quantityLabel.text=[#"Quantity:" stringByAppendingString:[self.emp valueForKey:#"quantity"]];
_storeLabel.text=[#"Store:" stringByAppendingString:[self.emp valueForKey:#"store"]];
_picLabel=[self.emp valueForKey:#"pic"];
_imagePicture.image=[self loadImage:_picLabel];
}
-(UIImage *)loadImage: (NSString *)name
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithString:name]];
UIImage* image = [UIImage imageWithContentsOfFile:path];
return image;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
#import <UIKit/UIKit.h>
#interface ItemTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *itemName;
#property (nonatomic, weak) IBOutlet UILabel *quantityLabel;
#property (nonatomic, weak) IBOutlet UILabel *shopLabel;
#end
#import "ItemTableViewCell.h"
#import "BrowseClickViewController.h"
#implementation ItemTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BrowseClickViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
#end
Most possibly , reason is that some of your appended strings values are nil.Do defensive coding.Check the below code sample and change all your code accordingly.
if([self.emp valueForKey:#"name"])
{
_nameLabel.text=[#"Name:" stringByAppendingString:[self.emp valueForKey:#"name"]];
}
I'm trying to implement an iCarousel that will pass information on to two other view controllers when an image is chosen. While the iCarousel loads perfectly and transitions to the next VC, the information is not displayed on the new VC.
The approach I chose was to create an NSObject file. I can't simply pass the info from VC to VC since I have several VC's that need the information and I'd prefer not to create a singleton or use AppDelegate if possible.
FYI: I do have a tap gesture recognizer added on top of the UIView that acts as the segue to the next VC if that makes any difference.
I've tried every possible tutorial out there and can't seem to figure out my problem. I just need to display a text label and a picture, which should really be pretty easy. Can someone take a quick glance at my code to see what I'm doing wrong?
My NSObject File:
#import <Foundation/Foundation.h>
#interface Stop : NSObject
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *image;
#end
First ViewController.h (with iCarousel on it):
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "iCarousel.h"
#import "DirectionsViewController.h"
#import "Stop.h"
#interface StopsMenuViewController : UIViewController <iCarouselDataSource, iCarouselDelegate>
#property (strong, nonatomic) IBOutlet iCarousel *carousel;
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
//Title
#property (nonatomic, strong) NSArray *stopTitles;
#property (nonatomic, strong) NSString *stopChosen;
//Image
#property (nonatomic, strong) NSArray *stopImages;
#property (nonatomic, strong) NSString *imageChosen;
#end
First ViewController.m:
#import "StopsMenuViewController.h"
#interface StopsMenuViewController () {
NSMutableArray *allInfo; }
#end
#implementation StopsMenuViewController
#synthesize titleLabel, carousel, stopImages, stopTitles, stopChosen, imageChosen;
- (void)awakeFromNib {
NSString *myPlist = [[NSBundle mainBundle] pathForResource:#"Chinatown" ofType:#"plist"];
NSDictionary *rootDictionary = [[NSDictionary alloc] initWithContentsOfFile:myPlist];
self.stopImages = [rootDictionary objectForKey:#"StopImages"];
self.stopTitles = [rootDictionary objectForKey:#"StopTitles"];
}
- (void)carouselDidScroll:(iCarousel *)carousel {
[titleLabel setText:[NSString stringWithFormat:#"%#", [self.stopTitles
objectAtIndex:self.carousel.currentItemIndex]]];
}
- (void)dealloc {
self.carousel.delegate = nil;
self.carousel.dataSource = nil;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"toDirections"])
{
DirectionsViewController *dvc = [segue destinationViewController];
int itemId = [self.carousel currentItemIndex];
NSIndexPath *path = [NSIndexPath indexPathForRow:itemId inSection:0];
Stop *current = [allInfo objectAtIndex:path.row];
[dvc setPassInfo:current];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.carousel.type = iCarouselTypeCoverFlow2;
allInfo = [[NSMutableArray alloc] init];
Stop *info = [[Stop alloc] init];
stopChosen = [NSString stringWithFormat:#"%#", [self.stopTitles objectAtIndex:self.carousel.currentItemIndex]];
[info setTitle:stopChosen];
[allInfo addObject:info];
info = [[Stop alloc] init];
self.imageChosen = [NSString stringWithFormat:#"%#", [self.stopImages
objectAtIndex:self.carousel.currentItemIndex]];
[info setTitle:self.imageChosen];
[allInfo addObject:info];
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.carousel = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel {
return [self.stopImages count];
}
- (NSUInteger)numberOfVisibleItemsInCarousel:(iCarousel *)carousel {
return 4;
}
- (UIView *)carousel:(iCarousel *)_carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view {
if (view == nil)
{
view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.stopImages objectAtIndex:index]]];
}
return view;
}
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index {
DirectionsViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"dvc"];
[self.navigationController pushViewController:dvc animated:YES];
}
#end
Second ViewController.h:
#import <UIKit/UIKit.h>
#import "Stop.h"
#interface DirectionsViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
#property (strong, nonatomic) IBOutlet UIImageView *imageBox;
#property (nonatomic, strong) Stop *PassInfo;
#property (nonatomic, strong) NSString *stopTitle;
#property (nonatomic, strong) NSString *myStopTitle;
#end
Second ViewController.m:
#import "DirectionsViewController.h"
#interface DirectionsViewController ()
#end
#implementation DirectionsViewController
#synthesize PassInfo;
- (void)viewDidLoad {
[super viewDidLoad];
[self.titleLabel setText:[PassInfo title]];
UIImage *image = [UIImage imageNamed:[PassInfo image]];
[self.imageBox setImage:image];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
Instead of
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index {
DirectionsViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"dvc"];
[self.navigationController pushViewController:dvc animated:YES];
}
Use
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index {
[self performSegueWithIdentifier:#"toDirections" sender:self];
}
In your code, you're instantiating the second view controller and presenting it, which is not the same as performing a segue. Therefore the method - prepareForSegue:sender: will not be invoked.
I have a project that displays a feed of statuses similar to other social networks. Each feed item has several button that do different things. 1 of the buttons opens a new viewcontroller that displays the comments that have been posted on a particular status. When this button is clicked and the view controller is opened i would like it to be a push segue so that their is a back button and the user can navigate back to the feed.
When this button is clicked and the new vc is launched some unique data about the particular status/cell being clicked needs to be sent to the "comments vc ". Where would the code for doing this go?
CUSTOM CELL .H
#import <UIKit/UIKit.h>
#interface FeedItemCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *DefaultImg;
#property (weak, nonatomic) IBOutlet UILabel *NameLabel;
#property (weak, nonatomic) IBOutlet UILabel *StatusLabel;
#property (weak, nonatomic) IBOutlet UILabel *timeLabel;
#property (nonatomic, copy) NSString *msg_id;
#property (nonatomic, copy) NSString *status;
#property (nonatomic, weak) IBOutlet UIButton* commentButton;
#property (nonatomic, weak) IBOutlet UIButton* bumpButton;
#property (strong, nonatomic) id delegate;
-(IBAction)viewComments:(id)sender;
-(IBAction)bump:(id)sender;
#end
#protocol CustomCellProtocol <NSObject>
- (void)EBCellPressed:(NSString *)cellName;
CUSTOM CELL .M
#import "FeedItemCell.h"
#import "CommentsViewController.h"
#import "NSDate+TimeAgo.h"
#interface FeedItemCell() <WYPopoverControllerDelegate>
{
}
- (IBAction)open:(id)sender;
- (void)close:(id)sender;
#end
#implementation FeedItemCell
#synthesize commentButton;
- (instancetype)initWithDelegate:(id)delegate {
self = [super init];
if (self) {
self.delegate = delegate;
// Initialization code
}
return self;
}
-(IBAction)bump:(id)sender{
[self.delegate EBCellPressed:#"NAME"];
}
- (IBAction)open:(id)sender
{
}
#end
publicFeed . M
#import "PublicFeedViewController.h"
#import "FeedItemCell.h"
#import "AFNetworking.h"
#import "UIImageView+WebCache.h"
#import "InboxDetailViewController.h"
#import "SWRevealViewController.h"
#import "CommentsViewController.h"
#import "NSDate+TimeAgo.h"
#interface PublicFeedViewController (){
NSArray *NameLabel;
NSArray *StatusLabel;
NSMutableArray *feedArray;
}
#end
#implementation PublicFeedViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//The below code prompts the user for push notifications. If allowed, code in AppDelegate takes over and stores the token.
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
// Do any additional setup after loading the view.
self.FeedTable.dataSource=self;
self.FeedTable.delegate=self;
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
_sidebarButton.target = self.revealViewController;
_sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
[UIApplication sharedApplication].networkActivityIndicatorVisible = TRUE;
[manager POST:#"www" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
//NSLog(#"JSON: %#", responseObject);
self->feedArray = [responseObject objectForKey:#"feed"];
[self.FeedTable reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = FALSE;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return feedArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifier=#"Cell";
FeedItemCell *Cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!Cell){
Cell = [[FeedItemCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSLog(#"FEED ARRAY: %#", self->feedArray);
NSDictionary *tempDictionary= [self->feedArray objectAtIndex:indexPath.row];
// Display recipe in the table cell
NSString *thumb_img = [tempDictionary objectForKey:#"thumb_img"];
NSString *thumb_path=#"http://buhzhyve.com/CI_REST_LOGIN/UPLOADS/thumbs/";
NSString *thumb_url = [thumb_path stringByAppendingString:thumb_img];
Cell.NameLabel.text=[tempDictionary objectForKey:#"first_name"];
Cell.StatusLabel.text=[tempDictionary objectForKey:#"message"];
Cell.msg_id=[tempDictionary objectForKey:#"msg_id"];
//Cell.status=[tempDictionary objectForKey:#"message"];
Cell.StatusLabel.lineBreakMode=0;
Cell.StatusLabel.numberOfLines=0;
NSString *commentCount = [tempDictionary objectForKey:#"comment_count"];
NSString *commentButtonText =[NSString stringWithFormat:#"Comments ( %# )",commentCount];
[Cell.commentButton setTitle:commentButtonText forState: UIControlStateNormal];
NSString *bumpCount = [tempDictionary objectForKey:#"bump_count"];
NSString *bumpButtonText =[NSString stringWithFormat:#"Bumps ( %# )",bumpCount];
[Cell.bumpButton setTitle:bumpButtonText forState: UIControlStateNormal];
//[Cell.StatusLabel sizeToFit];
NSString *created_string=[tempDictionary objectForKey:#"created"];
double created_double = created_string.doubleValue;
NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:created_double];
NSString *ago = [date timeAgo];
Cell.timeLabel.text=ago;
//Cell.DefaultImg.image = [UIImage imageNamed:#"buhz_mini_logo.png"];
[Cell.DefaultImg setImageWithURL:[NSURL URLWithString:thumb_url]
placeholderImage:[UIImage imageNamed:#"buhz_mini_logo.png"]];
return Cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Ideally you should do lazy loading so that instead of creating a new textView each time, you just reuse the same one.
UITextView *temp = [[UITextView alloc] initWithFrame:CGRectMake(82, 26, self.FeedTable.frame.size.width, 18)]; //This initial size doesn't matter
NSDictionary *tempDictionary= [self->feedArray objectAtIndex:indexPath.row];
NSString *status = [tempDictionary objectForKey:#"message"];
temp.font =[UIFont fontWithName:#"System" size:12];
temp.text = status;
CGFloat textViewWidth = 218;
CGRect tempFrame = CGRectMake(82,26,textViewWidth,18); //The height of this frame doesn't matter.
CGSize tvsize = [temp sizeThatFits:CGSizeMake(tempFrame.size.width, tempFrame.size.height)]; //This calculates the necessary size so that all the text fits in the necessary width.
//Add the height of the other UI elements inside your cell
return tvsize.height + 70;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"commentSegue"]) {
}
}
#end
publicfeed .h
#import <UIKit/UIKit.h>
#interface PublicFeedViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *FeedTable;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
- (IBAction)addItem;
#end
So assuming that you're creating this button in code, this is how you could handle this.
This first line tells the button that when it's pressed, it needs to call this specific selector/method sent as the action.
[button addTarget:self action:#selector(showNextViewController) forControlEvents:UIControlEventTouchUpInside];
Then you would create this method in the same class.
- (void) showNextViewController
{
NewViewController *newViewController = [[NewViewController alloc] init]; //Edit this line of course to fit for your situation. I'm not sure if you're loading from an XIB or from a Storyboard, or neither.
newViewController.someVariable = someVariable;
newViewController.someOtherVariable = someOtherVariable;
[[[[[UIApplication sharedApplication] delegate] window] rootViewController].navigationController pushViewController:view animated:YES];
}
This will send the necessary data to the new view controller, and it will also display the new view on the screen with a back button.
Hope this works!
1. Ok so lets pretend this is your custom cell class.
in your .h file of the custom cell you need to add a protocol.
#import <UIKit/UIKit.h>
#interface CustomCell : UIView
#property (strong, nonatomic) id delegate; //this is used for sending messages out of the custom cell
//init
- (id)initWithFrame:(CGRect)frame andCatName:(NSString *)name andDelegate:(id)delegate;
#end
#protocol CustomCellProtocol <NSObject>
-(void)customCellSelected:(NSString *)cellName;
#end
what we actually did is something like creating a custom event that the class can throw out and everyone who subscribes to that can run a method when customCellSelected is thrown.
2. now when you create each custom cell with the init method you need to provide a delegate which kind of points to which class should the custom cell transfer the call to customCellSelected so in the init method you set that delegate.
- (id)initWithFrame:(CGRect)frame andDelegate:(id)delegate {
self = [super initWithFrame:frame];
if (self) {
self.delegate = delegate; //setting which class should be called when calling protocol methods.
// Your initialization code
}
return self;
}
3. now in your .m file of the custom cell, when the user presses your button and you enter your method , let it be buttonPressed
- (IBAction) buttonPressed:(id)sender {
[self.delegate customCellSelected:#"THE CELL'S NAME"]; // calling the protocol method.
}
now the call to the delegate method should be transferred to the vc because when you create the custom cell you use initWithFrame:(CGRect)frame andDelegate:(id)delegate and you transfer self as the delegate , so when [self.delegate customCellSelected:#"THE CELL'S NAME"]; is called it is actually called on the vc.
4. this is how you create the custom cell in the vc:
customCell *tempView = [[customCell alloc] initWithFrame:CGRectMake(X, Y, Width, Height) andDelegate:self]; // here you set the vc as the delegate
5.and now all you have to do is add the method customCellSelected to your vc code so it can called when the customCell is calling it.
- (void)customCellSelected:(NSString *)cellName {
self.selectedCell = cellName;
[self performSegueWithIdentifier:#"SelectedCell" sender:self];
}
6.then add this in the vc:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"SelectedCell"]) {
LevelSelectViewController *levelSelectViewController = (LevelSelectViewController *)segue.destinationViewController;
levelSelectViewController.cellName = self.selectedCell;
}
}
7.only thing you have to remember is to create a segue from your first vc to the second like this:
I'm trying to create a SplitViewController view but I get the following warning:
Property splitViewController requires a method setSplitViewController to be defined -use #Synthesize,#dynamic or provide a method implementation in this class implement.
Here is the code
///AppDelegate.h
#class ViewController;
#class DetailViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate, UISplitViewControllerDelegate>
{
UISplitViewController *splitViewController;
ViewController *viewcontroller;
DetailViewController *detailViewController;
}
#property (nonatomic,retain) UIWindow *window;
#property (nonatomic,retain) DetailViewController *detailViewController;
#property(nonatomic,retain) UISplitViewController *splitViewController;
#property (nonatomic,retain) ViewController *viewController;
#end
///AppDelegate.m"
#import "ViewController.h"
#import "DetailViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
#synthesize splitviewController;
#synthesize detailViewController;
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ViewController *rootViewController = [[ViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
rootViewController.detailViewController = detailViewController;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
splitViewController.delegate = detailViewController;
[self.window makeKeyAndVisible];
return YES;
}
///ViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface ViewController : UITableViewController{
DetailViewController *detailViewController;
NSMutableArray *phone;
}
#property (nonatomic,retain)IBOutlet DetailViewController *detailViewController;
#property (nonatomic,retain) NSMutableArray *phone;
#end
///ViewController.m
#import "ViewController.h"
#import "DetailViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize detailViewController,phone;
- (CGSize)contentSizeForViewInPopoverView {
return CGSizeMake(320, 600);
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.phone = [[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"phone" ofType:#"plist"]] retain];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [phone count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Configure the cell.
cell.textLabel.text = [self.phone objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
*/
detailViewController.detailItem = [self.phone objectAtIndex:indexPath.row];
}
- (void)dealloc {
[detailViewController release];
[super dealloc];
}
#end
In ur code, you haven't synthesized your splitViewController property. Since You have not synthesized it the property, the compiler is issuing a warning asking u to either synthesize the property so that it can generate setters and getters automatically for your convinienvce (You can use the generated setters and getters using . notation as in self.splitViewController so synthesize it as
#synthesize splitViewController = _splitViewController
or
implement your own custom setter and getter as
//setter
- (void)setSplitViewController:(UISplitViewController*)splitViewController_ {
//assuming your property has retain identifier
if (splitViewController != splitViewController_) {
[splitViewController release];
splitViewController = [splitViewController_ retain];
}
}
//getter
- (UISplitViewController*)splitViewController {
return splitViewController;
}
or
declaring the property as dynamic using #dynamic splitViewController . This means that the setter and getter for the property will be provided from somewhere else.
EDIT:
replacedidFinishLaunchingWithOptions method in appDelegate.m with the following:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_viewController = [[ViewController alloc] initWithNibName:#"ViewController's nib name" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:_viewController];
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
rootViewController.detailViewController = detailViewController;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
splitViewController.delegate = detailViewController;
self.window.rootViewController = splitViewController;
return YES;
}
also edit the dealloc:
- (void)dealloc
{
[_window release];
[_viewController release];
[splitViewController release];
[detailViewController release];
[super dealloc];
}
And in viewController viewDidLoad replace self.phones line with this
self.phone = [[NSArray arrayWithObjects:#"Cell ONE",#"Cell TWO",#"Cell THREE",#"Cell FOUR",#"Cell FIVE",#"Cell SIX", nil];
this is just for testing that the array part is loading properly..so that you can see the cells if they are getting created. put a break point in cellForRowAtIndexPath method and see if its getting called
and then finally in didSelect see if the detailItem iVar is not nil.
And Yes, check the NIB names properly before loading them, and also that all outlets in the NIB are properly connected.
Cheers and Have fun.
The problem is you misspelled splitViewController in your #synthesize statement -- you didn't capitalize the v.
You wouldn't run into this problem if you did it the easy way. There's no need for either the instance variables or the #synthesize statements any more -- you get both automatically when create the property.
In your case add #synthesize splitViewController = _splitViewController; and detailViewController = _ detailViewController;
Here is useful code for, how can i add UISplitViewController.
/// AppDelegate.h file
#import <UIKit/UIKit.h>
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, UISplitViewControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) UISplitViewController *splitViewController;
#property (nonatomic, strong) MasterViewController *masterVC;
#property (nonatomic, strong) DetailViewController *detailVC;
#property (nonatomic, strong) UINavigationController *mvcNavCon;
#property (nonatomic, strong) UINavigationController *dvcNavCon;
#end
/// AppDelegate.m File
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.masterVC = [[MasterViewController alloc] init];
self.mvcNavCon = [[UINavigationController alloc] initWithRootViewController:self.masterVC];
self.detailVC = [[DetailViewController alloc] init];
self.dvcNavCon = [[UINavigationController alloc] initWithRootViewController:self.detailVC];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = self;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:self.mvcNavCon, self.dvcNavCon,nil];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
return YES;
}
i search for a way to have multiple detail view in iPad application and i find the sample code in apple developer site http://developer.apple.com/library/ios/#samplecode/MultipleDetailViews/Introduction/Intro.html , but now i want to have navigation in detail view which this sample does not cover, i add uinavigationcontroller to detail view as :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ReportsViewController_iPad *master = [[ReportsViewController_iPad alloc] initWithNibName:#"ReportsViewController_iPad" bundle:nil];
DetailViewController_iPad *detail = [[DetailViewController_iPad alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *masterNavController = [[[UINavigationController alloc] initWithRootViewController:master ] autorelease];
UINavigationController *detailNavController = [[[UINavigationController alloc] initWithRootViewController:detail ] autorelease];
splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavController , detailNavController, nil];
[window addSubview:splitViewController.view];
[window makeKeyAndVisible];
return YES;
}
but when i run the sample i got error
[UINavigationController showRootPopoverButtonItem:]: unrecognized selector sent to instance...
showRootPopoverButtonItem is a method define in a protocol in RootViewController
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
---- ReportsViewController.h
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#protocol DetailViewControllerManagerDelegate
-(void) didSelectRowAtIndexPathPopOver:(NSString *)ID;
#end
#interface ReportsViewController_iPad : ReportsViewController<UISplitViewControllerDelegate , DetailViewControllerManagerDelegate>
{
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
#property(nonatomic, retain) id<DetailViewControllerManagerDelegate> delegate;
-(void)didSelectRowAtIndexPath:(NSString*)ID;
#end
--DetailViewController.h
#import <UIKit/UIKit.h>
#import "ReportsViewController_iPad.h"
#interface DetailViewController_iPad : UIViewController<SubstitutableDetailViewController>
{
UIToolbar *toolbar;
}
#property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
#end
--DetailViewController.m
#import "DetailViewController_iPad.h"
#implementation DetailViewController_iPad
#synthesize toolbar;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark Managing the popover
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray insertObject:barButtonItem atIndex:0];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button from the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray removeObject:barButtonItem];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)dealloc {
[toolbar release];
[super dealloc];
}
#end
So Thanks in advance.
Where definition of method showRootPopoverButtonItem is present, seems like this is not defined. You need to define it.
If you want to avoid crash then you can use -
if ([aViewController respondsToSelector:#selector(showRootPopoverButtonItem:)]) {
[aViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
EDIT -
I have checked this and found what you are doing wrong , for e.g. code in willHideViewController-
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
this is expecting a view controller, while you are passing navigation controller which in turn has view controller(similar at some other position), so you need to alter these codes as well if you want to pass navigation controller from app delegate.