I am building a simple app with a custom bar tab which loads the content of the ViewController from a UITableView located in another ViewController.
However, every time I try to scroll on the tableview, I get an exc_bad_access error. I enabled NSzombies and guard malloc to get more info on the issue.
In the console I get:
"message sent to deallocated instance 0x19182f20"
and after profiling I get:
# Address Category Event Type RefCt Timestamp Size Responsible Library Responsible Caller
56 0x19182f20 FirstTabBarViewController Zombie -1 00:16.613.309 0 UIKit -[UIScrollView(UIScrollViewInternal) _scrollViewWillBeginDragging]
Here is a bit of the code of the ViewController in which the error occurs:
.h file:
#import <UIKit/UIKit.h>
#import "DataController.h"
#interface FirstTabBarViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView* tabBarTable;
}
#property (strong, nonatomic) IBOutlet UIView *mainView;
#property (strong, nonatomic) IBOutlet UITableView *tabBarTable;
#property (nonatomic, strong) DataController *messageDataController;
#end
.m file:
#import "FirstTabBarViewController.h"
#import "DataController.h"
#interface FirstTabBarViewController ()
#end
#implementation FirstTabBarViewController
#synthesize tabBarTable=_tabBarTable;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)awakeFromNib
{
[super awakeFromNib];
self.messageDataController=[[DataController alloc] init];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.messageDataController countOfList];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"mainCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
};
NSString *expenseAtIndex = [self.messageDataController
objectInListAtIndex:indexPath.row];
[[cell textLabel] setText:expenseAtIndex];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
#end
This FirstTabBarViewController is loaded in the MainViewController with the following custom segue:
#import "customTabBarSegue.h"
#import "MainViewController.h"
#implementation customTabBarSegue
-(void) perform {
MainViewController *src= (MainViewController *) [self sourceViewController];
UIViewController *dst=(UIViewController *)[self destinationViewController];
for (UIView *view in src.placeholderView.subviews){
[view removeFromSuperview];
}
src.currentViewController =dst;
[src.placeholderView addSubview:dst.view];
}
#end
The Datacontroller class is just a simple NSMutableArray containing strings.
I am using ARC so I don't understand where the memory management error comes from. Does anybody have a clue?
Any help much appreciated ;)
Thanks!!
Ok... Thank you for the code sample...
See UIStoryboardSegue documentation, when you implement perform in your customTabBarSegue, you're responsible for setting, in the end, the correct relationship between your 2 viewControllers.
You have 2 possibilities:
setting dst as a modal child (then src is presentingViewController of dst), adding this code at the end of perform: [src presentViewController:dst animated:NO completion:nil];
setting dst as a child viewController of src - adding this code : [src addChildViewController:dst];
at the end of perform, but then, you have to remove it somewhere, or remove other childs in the same method....
Here's an implementation
#implementation customTabBarSegue
-(void) perform {
MainViewController *src= (MainViewController *) [self sourceViewController];
UIViewController *dst=(UIViewController *)[self destinationViewController];
for (UIView *view in src.placeholderView.subviews){
[view removeFromSuperview];
}
src.currentViewController =dst;
[src.placeholderView addSubview:dst.view];
// this container only show 1 viewController at a time, so we can remove previous ones
for (UIViewController *vc in src.childViewControllers) {
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
}
//then add the new View controller as child
[src addChildViewController:dst];
}
#end
Anyway, you should definitively look more into UIViewController containment...
Related
I'm having two view controller A and B. when click button on view controllerA it will navigate to view controllerB and their is a tableview with textlabel,when i click on tableviewcell i want to navigate back into viewcontrollerA and want to pass that textlabel value back to viewcontrollerA
if you are using push seque is the worst way, reason you increase the memory in your stack trace.
you can do this in multiple ways, search once in google you get multiple answer related to this
UnWind Segue
Protocols & delegates
local database method
using Singleton class.
Using bean object method.
using Plist
finally go for NSUserDefault
I created a sample using Protocols and Delegates, as follows:
ViewController.m
#import "ViewController.h"
#import "ColorsTableViewController.h"
#interface ViewController () <ColorsDelegate>
#property (weak, nonatomic) IBOutlet UILabel *textDataLabel;
- (IBAction)goButtonTapped:(id)sender;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)sendColor:(NSString *)colorName{
self.textDataLabel.text = colorName;
}
- (IBAction)goButtonTapped:(id)sender {
ColorsTableViewController *colorsTableViewController=(ColorsTableViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"colorTableIdentifier"];
colorsTableViewController.delegate = self;
[self.navigationController pushViewController:colorsTableViewController animated:YES];
}
#end
ColorsTableViewController.h
#import <UIKit/UIKit.h>
#protocol ColorsDelegate <NSObject>
#optional
- (void)sendColor:(NSString *)colorName;
#end
#interface ColorsTableViewController : UIViewController
#property (nonatomic, assign) id<ColorsDelegate> delegate;
#end
ColorsTableViewController.m
#import "ColorsTableViewController.h"
#interface ColorsTableViewController () <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UITableView *colorsTableView;
#property (strong, nonatomic) NSArray *colorsArray;
#end
#implementation ColorsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.colorsArray = #[#"Red",#"Green",#"Blue",#"Brown",#"Yellow"];
[self.colorsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"colorCell"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.colorsArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *myCell = [self.colorsTableView dequeueReusableCellWithIdentifier:#"colorCell" forIndexPath:indexPath];
UILabel *myTextLabel = [myCell.contentView viewWithTag:100];
if(!myTextLabel)
{
myTextLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 5, CGRectGetWidth(myCell.frame), CGRectGetHeight(myCell.frame))];
myTextLabel.tag = 100;
}
myTextLabel.text = self.colorsArray[indexPath.row];
[myCell.contentView addSubview:myTextLabel];
return myCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *myCell = (UITableViewCell *)[self.colorsTableView cellForRowAtIndexPath:indexPath];
UILabel *myTextLabel = [myCell.contentView viewWithTag:100];
if(myTextLabel)
{
[_delegate sendColor:myTextLabel.text];
}
}
Screenshot:
Here is my GitHub Link, please download and check:
https://github.com/k-sathireddy/sendDataBack
FirstPage.h
#import <UIKit/UIKit.h>
#import "StudentPage.h"
#interface FirstPage : UIViewController <UITableViewDelegate,UITableViewDataSource,StudentInfoDelegates>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)addButtonAction:(id)sender;
#end
FirstPage.m
#import "FirstPage.h"
#interface FirstPage ()
#end
#implementation FirstPage
{
NSMutableArray *firstPageArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
//[self performSegueWithIdentifier:#"StudentInfo" sender:sender];
/*StudentPage *student=[[StudentPage alloc]init];
student.delegates=self;*/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//the next following didn't created..
//the RowAtIndexPath are not been executed..
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *concateValue=#"";
NSMutableDictionary *studentSecondDictionary=[[NSMutableDictionary alloc]init];
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
cell=[[UITableViewCell alloc]initWithFrame:CGRectZero];
[cell setBackgroundColor:[UIColor redColor]];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setIndentationWidth:0.0];
studentSecondDictionary=[firstPageArray objectAtIndex:indexPath.row];
NSString *name1=[studentSecondDictionary valueForKey:#"NAME"];
NSString *regno1=[studentSecondDictionary valueForKey:#"REGNO"];
NSString *marks1=[studentSecondDictionary valueForKey:#"MARKS"];
NSString *rank1=[studentSecondDictionary valueForKey:#"RANK"];
concateValue=[[[[[[name1 stringByAppendingString:#" "]stringByAppendingString:regno1]stringByAppendingString:#" "]stringByAppendingString:marks1]stringByAppendingString:#" "]stringByAppendingString:rank1];
cell.textLabel.text=concateValue;
}
return cell;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return firstPageArray.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
- (IBAction)addButtonAction:(id)sender {
StudentPage *stdView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
stdView.delegates=self;
[self.navigationController pushViewController:stdView animated:YES];
//[self.view addSubview:stdView.view];
}
-(void)didFinishSave:(NSMutableArray *)in_studentList{
firstPageArray=[[NSMutableArray alloc]init];
firstPageArray=in_studentList;
[self.tableView reloadData];
}
#end
StudentPage.h
#import <UIKit/UIKit.h>
#protocol StudentInfoDelegates
-(void)didFinishSave:(NSMutableArray*)in_studentList;
#end
#interface StudentPage : UIViewController<UITextFieldDelegate>
#property(assign,nonatomic)id<StudentInfoDelegates> delegates;
#property (strong, nonatomic) IBOutlet UITextField *name;
#property (strong, nonatomic) IBOutlet UITextField *regno;
#property (strong, nonatomic) IBOutlet UITextField *marks;
#property (strong, nonatomic) IBOutlet UITextField *rank;
- (IBAction)save:(UIButton *)sender;
#end
StudentPage.m
#import "StudentPage.h"
#import "FirstPage.h"
#implementation StudentPage
{
NSMutableArray *studentArray;
NSMutableDictionary *StudentDictionary;
}
#synthesize name,regno,marks,rank;
#synthesize delegates;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
- (IBAction)save:(UIButton *)sender {
studentArray=[[NSMutableArray alloc]init];
StudentDictionary=[[NSMutableDictionary alloc]init];
[StudentDictionary setValue:name.text forKey:#"NAME"];
[StudentDictionary setValue:regno.text forKey:#"REGNO"];
[StudentDictionary setValue:marks.text forKey:#"MARKS"];
[StudentDictionary setValue:rank.text forKey:#"RANK"];
[studentArray addObject:StudentDictionary];
[delegates didFinishSave:studentArray];
NSLog(#"%#",studentArray);
FirstPage *firstView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier1"];
[self.navigationController pushViewController:firstView animated:YES];
}
#end
As #BiWoj said in the comments, you are checking for
if (cell==nil)...
and rely on that check to go through the first time so you can fill out your data. This is wrong, you instead dequeue the cell and then when it's not nil you can start putting your data in its views. The only reason that cell will be nil is when you dequeue, using a non-existent identifier i.e. it should never happen.
First just check your delegate method is getting called or not when you click on save button.
I think you forgot to set delegate to self before
[delegates didFinishSave:studentArray];
It should be
self.delegate = delegates
[delegates didFinishSave:studentArray];
If this does not work please check that, you are pushing student page from first page like this
- (IBAction)addButtonAction:(id)sender {
StudentPage *stdView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
stdView.delegates=self;
[self.navigationController pushViewController:stdView animated:YES];}
And one again on your save action method of student page you are pushing first page like this.
FirstPage *firstView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier1"];
[self.navigationController pushViewController:firstView animated:YES];
Well i guess instead of that you have to just use
[self.navigationController popToRootViewControllerAnimated:YES];
There is no need to push again the same controller you just have to pop to base controller.
What I'm trying to do is have a list of counties in a table view. When you click a county, another table view will show a list of resources you can select. I am using storyboards and Objective-C.
Here is my storyboard.
I don't want to nest the options into one table view because I think there are too many choices to be efficiently nested.
Here is my .h file for the county list table view:
// SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
#end
My .m file for the county list table view:
// SecondViewController.m
#import "SecondViewController.h"
#import "DetailViewController.h"
#interface SecondViewController ()
#property (nonatomic, strong) NSArray *tableData;
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableData = #[#"Carter", #"Greene", #"Hancock", #"Hawkins", #"Johnson", #"Sullivan", #"Unicoi", #"Washington"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[DetailViewController class]])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *name = self.tableData[indexPath.row];
[(CountyViewController *)segue.destinationViewController setName:name];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tableData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.tableData[indexPath.row];
return cell;
}
#end
The County Resources .h file I want to display in table view format:
// CountyViewController.h
#import <UIKit/UIKit.h>
#interface CountyViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
The .m file:
// CountyViewController.m
#import "CountyViewController.h"
#import "CountyDetail.h"
#interface CountyViewController ()
#end
#implementation CountyViewController {
NSArray *counties;
}
#synthesize tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize table data
counties = [NSArray arrayWithObjects:#"Resource1", #"Resource2", #"Resource3", #"Resource4", #"Resource5", #"Resource6", #"Resource7", #"Resource8", #"Resource9", nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [counties count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [counties objectAtIndex:indexPath.row];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showCountyInfo"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
CountyDetail *destViewController = segue.destinationViewController;
destViewController.countyName = [counties objectAtIndex:indexPath.row];
}
}
#end
Lastly, the detail of the resource clicked:
// CountyDetail.h
#import <UIKit/UIKit.h>
#interface CountyDetail : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *countyLabel;
#property (nonatomic, strong) NSString *countyName;
#end
And the .m file:
// CountyDetail.m
#import "CountyDetail.h"
#interface CountyDetail ()
#end
#implementation CountyDetail
#synthesize countyLabel;
#synthesize countyName;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Set the Label text with the selected county
countyLabel.text = countyName;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
So my goal is to have the county selection go to another array of resources in another table view. I'm guessing I'm going to need a lot more arrays, but I just don't know the format or structure. I hope this is enough information, and if anyone can explain their answer, that would be extremely helpful. Thanks!
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
You can follow this delegate send the message to another tableView or others.
I am trying to copy the array from tableview controller to view controller. I have checked the code multiple times and it seems to be okay.
//Delegate class
#import <UIKit/UIKit.h>
#protocol Category <NSObject>
#required
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory;
#end
#interface Categories : UIViewController <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic) id<Category> delegate;
#property (nonatomic,strong) NSArray *sports;
#property (strong, nonatomic) IBOutlet UITableView *tableview;
#property (nonatomic,strong) NSMutableArray *selectedIndexes;
#end
//Delegate methods
#import "Categories.h"
#interface Categories ()
{
NSMutableArray *array ;
}
#end
#implementation Categories
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_sports= [[NSArray alloc] initWithObjects: #"Baseball", #"Soccer", #"Hockey",
#"Other",nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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 _sports.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
array = [[NSMutableArray alloc]init];
// Configure the cell...
cell.textLabel.text=[self.sports objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryNone)
{ [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
[array addObject:cellText];
}else if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryCheckmark){
[tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryNone;
[array removeObject:cellText];
}
}
- (IBAction)doneButton:(id)sender {
[self.delegate delegateMethodForCategory:array];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
#import <UIKit/UIKit.h>
#import "Categories.h"
#interface ActivityCreator : UIViewController <UIPopoverPresentationControllerDelegate, Category>
#property (nonatomic) Categories *requestClass;
#property (nonatomic,strong) NSMutableArray *arrayOfSports;
#end
//This class implements delegate
import "ActivityCreator.h"
#interface ActivityCreator ()
#end
#implementation ActivityCreator
- (void)viewDidLoad {
[super viewDidLoad];
[self settingUp];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
return UIModalPresentationNone;
}
-(void)settingUp{
_requestClass = [[Categories alloc]init];
self.requestClass.delegate = self;
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"hubabuba"]){
Categories *pop = (Categories *)segue.destinationViewController;
pop.modalPresentationStyle = UIModalPresentationPopover;
pop.popoverPresentationController.delegate = self;
}
}
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory {
_arrayOfSports = arrayOfCategory;
NSLog(#"%#",_arrayOfSports);
}
Any guidance where I am doing wrong will be of great help. Have been stuck on this for a while.
The delegate method is not being called at all.
Thanks
Set the delegate of Categories class in prepareForSegue method instead of setting in settingUp method.
Write
pop.delegate = self;
In prepareForSegue method.
I'm trying to make a Master-Detail app that displays a list of Sounds on the master view. When you tap the sound, you go to the detail screen, and it displays the Sound you chose as a label, then shows a short movie of the sound. My problem is, all the sounds show as the label the name of the first sound in the list. When I tap on Sound B, the detail screen shows "Sound B." When I tap on tSound F, the detail screen shows "Sound B."
No errors or warnings come up. Any ideas?
Thanks in advance.
slfViewController.h
#import <UIKit/UIKit.h>
#interface slfViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
slfViewController.m
#import "slfViewController.h"
#import "slfSoundDetailViewController.h"
#interface slfViewController ()
#end
#implementation slfViewController
{
NSArray *tableData;
NSArray *thumbnails;
}
#synthesize tableView = _tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tableData = [NSArray arrayWithObjects:
#"B Sound",
#"Ch Sound",
#"D Sound",
#"F Sound",
...
#"Zh Sound",
nil];
thumbnails = [NSArray arrayWithObjects:
#"b.jpg",
#"ch.jpg",
#"d.jpg",
#"f.jpg",
...
#"zh.jpg",
nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showSoundDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
slfSoundDetailViewController *destViewController = segue.destinationViewController;
destViewController.soundName = [tableData objectAtIndex:indexPath.row];
}
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"soundCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
return cell;
}
#end
slfSoundDetailViewController.h
#import <UIKit/UIKit.h>
#interface slfSoundDetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *soundLabel;
#property (nonatomic, strong) NSString *soundName;
#end
slfSoundDetailViewController.m
#import "slfSoundDetailViewController.h"
#interface slfSoundDetailViewController ()
#end
#implementation slfSoundDetailViewController
#synthesize soundLabel;
#synthesize soundName;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
soundLabel.text = soundName;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
You’re only setting soundLabel.text = soundName in viewDidLoad… so it’s only being called once (when the view controller’s view is first loaded). This app is most likely reusing the same instance of slfSoundDetailViewController so it doesn’t reload its view.
You’ll probably want to override either -[slfSoundDetailViewController setSoundName:] or -[slfSoundDetailViewController viewWillAppea:] and set soundLabel.text there.