UITableView to detail UITableView drill down using storyboard - objective-c

I am trying to develop a RSS Reader drill down table with storyboard in a Tab bar app. I have managed to populate my RootTableViewController with the parsed XML. I am now having a problem working out how to get each row in my RootTableViewController to point and to pass the data from the selected cell to another DetailTableViewController.
This is part of my code to parse the XML and to populate the RootTableViewController:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [stories count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"AdvCurrentCelly";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString *description = [[stories objectAtIndex: storyIndex] objectForKey: #"description"];
NSString *title = [[stories objectAtIndex: storyIndex] objectForKey: #"title"];
//This populates the prototype cell 'AdvCurrentCelly'
cell.textLabel.text = title;
//cell.textLabel.text = date;
cell.detailTextLabel.text = description
return cell;
}
In Storyboard, the name of the segue from the RootTableViewContoller cell to the DetailTableViewController is ShowADVDetail
Help much appreciated
Jan

You can pass any type of data, but I'll show you how to pass your Title string. Lets call it myString. First you need to add a property in your DetailTableViewController.h to store your string:
#property (strong, nonatomic) NSString *myString
In you RootTableViewController you need to tell the segue what to do. Use this code as an example:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Refer to the correct segue
if ([[segue identifier] isEqualToString:#"ShowADVDetail"]) {
// Reference to destination view controller
DetailTableViewController *vc = [segue destinationViewController];
// get the selected index
NSInteger selectedIndex = [[self.teamTable indexPathForSelectedRow] row];
// Pass the title (from your array) to myString in DetailTableViewController:
vc.myString = [NSString stringWithFormat:#"%#", [[stories objectAtIndex:selectedIndex] objectForKey: #"Title"]];
}
}

Related

UISearch and TableViewCell

When I searching and then select row that opens only the first letter (for example A.Others letters don't open. NSLog and breakpoint not helping. I don't understand what is the problem.
#synthesize propertyList, letters, filteredNames, searchController , arrayPlace;
- (void)viewDidLoad {
[super viewDidLoad];
............
filteredNames = [[NSMutableArray alloc]init];
searchController = [[UISearchController alloc]init];
self.searchController.searchResultsUpdater = self;
NSString *path = [[NSBundle mainBundle] pathForResource:#"names" ofType:#"plist"];
self.propertyList = [NSDictionary dictionaryWithContentsOfFile:path];
self.letters = [[self.propertyList allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
#pragma mark - Table view data source
.......
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"cell bg1.png"]];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
if (tableView.tag == 1){
NSString *letter = self.letters[indexPath.section];;
NSArray *keyValues = [[self.propertyList[letter] allKeys] sortedArrayUsingSelector:#selector(compare:)];
cell.textLabel.text = keyValues[indexPath.row];
} else{
cell.textLabel.text = filteredNames[indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *keyTitle = cell.textLabel.text;
NSDictionary *peopleUnderLetter = [self.propertyList objectForKey:self.letters[indexPath.section]];
__block NSDictionary *selectedPerson = nil;
[peopleUnderLetter enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:keyTitle]) {
selectedPerson = obj;
*stop = YES;
}
}];
if (selectedPerson) {
DetailViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Push the view controller.
[self.navigationController pushViewController:vc animated:YES];
[vc setDictionaryGeter:selectedPerson];
}
}
And :
#pragma mark Search Display Delegate Methods
-(void)searchDisplayController:(UISearchController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
-(BOOL)searchDisplayController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filteredNames removeAllObjects];
if (searchString.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.searchBar.text];
for (NSString *letter in letters) {
NSArray *matches = [[self.propertyList[letter] allKeys]filteredArrayUsingPredicate:predicate];
[filteredNames addObjectsFromArray:matches];
}
}
return YES;
}
Search bar fails and he does select row after searching
If you want more information just say it to me by answers and I will edit my question and then you will edit your answer
Please explain again clearly. You search using any alphabet, it shows the result which has only "A". Is this what you're trying to say ? If so, then remove the above code and try the below approach :-
Drag a search bar into the view controller and set its delegate to self (You'll find its property in the storyboard's delegate property
to the view controller).
Add UISearchBarDelegate in the .h file that will take care of automatically calling the appropriate methods of the search bar of
which the delegate is set to self.
Use the below method to detect the search. You can filter the NSArray here and reload the table.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
}
I'd recommend you to go through some basic tutorials about iOS development before getting deeper. All the best and I hope it helps you...
Screenshot

Trouble passing information through segue

Alright. I'm having trouble passing data through a segue from one UITableViewController to another. The proper information does not load. Without a bunch of endless talk about the setup, here goes:
On the upper (passing) viewController side:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"deriv"]) {
NSIndexPath *indexPath = [self.tableView2 indexPathForSelectedRow];
DerivationController *destViewController = segue.destinationViewController;
destViewController.derivationName = [equationsList2 objectAtIndex:indexPath.row];
}
On the receiving viewController side:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"derivCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [derivations objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [details objectAtIndex:indexPath.row];
return cell;
}
equationsList2 is a list of equations in an NSArray instance. Depending on which one is selected, cell.textLabel and cell.detailTextLabel are set accordingly from NSArrays "derivations" and "details".
The declaration for DerivationController.h is on the passing viewController's header list.
No errors are thrown.
Any ideas?
Code for setting 'derivations' and 'detail':
if ([_derivationName isEqualToString:#"Momentum-Velocity"])
{
// Equation 1:
derivations = [NSArray arrayWithObjects:
#"Momentum",
#"Mass",
#"Velocity",
nil];
details = [NSArray arrayWithObjects:
#"Momentum units in kg ∙ m/s",
#"Mass units in kilograms (kg)",
#"Velocity units in meters/second (m/s)",
nil];

How to delegate an open source tableview badge to UITableview

I know similar questions have been asked few times about how to add badge to tableviewcell, but I could not make it working
Basically what I want is to show user a simple notification either a red number at the right part of the table view cell or a rectangle or like native email app.
So I have tried both of this two source code TDbadgcell and DDbadgecell
Now the problem is I can not delegate them, I have to import their .h classes and call either one of the below functions in my table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
TDBadgedCell *cell = [[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
or
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
DDBadgeViewCell *cell = (DDBadgeViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[DDBadgeViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
But when I do that my tableView didSelectRowAtIndexPath: and (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender methods are not working, I can click the rows but they stay higlihted blue nothing happens also my arrow at the right side of the table is dissappears.
So how can I achieve to add a badge to table view cell row either with above source codes or any other methods?
EDIT:::
After putting NSLOG I can see that did select row is called but perform segue still does not work. Without adding any of the above code it works perfect.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *CellIdentifier = #"MeetingCell";
static NSString *CellIdentifier = #"Cell";
DDBadgeViewCell *cell = (DDBadgeViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[DDBadgeViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *description =#":";
NSString *name =#"";
NSString *fileStatus=#"";
name = [[self agenda] getFileNameWithSection:[indexPath section] Row:[indexPath row]];
description = [[self agenda] getFileDescriptionWithSection:[indexPath section] Row:[indexPath row]];
fileStatus = [[self agenda] getFileStatusWithFileName:name];
NSString * cellLabel = [NSString stringWithFormat:#" %# : %#",description,name];
//alloc row images
UIImage *docImage = [UIImage imageNamed:#"ICON - Word#2x.png"];
UIImage *xlsImage = [UIImage imageNamed:#"ICON - Excel#2x.png"];
// UIImage *picImage = [UIImage imageNamed:#"ICON - Image#2x.png"];
UIImage *pdfImage = [UIImage imageNamed:#"pdf icon#2x copy.png"];
UIImage *pptImage = [UIImage imageNamed:#"ICON - PPT#2x.png"];
//Determine what status to display for a file
//No need to that since wee use push notification
if ([fileStatus isEqualToString:#"new"]){
cellLabel = [NSString stringWithFormat:#"%# (%#)",cellLabel,#"New"];
cell.badgeText = [NSString stringWithFormat:#"Update"];
cell.badgeColor = [UIColor orangeColor];
}else if ([fileStatus isEqualToString:#"outdated"]){
cellLabel = [NSString stringWithFormat:#"%# (%#)",cellLabel,#"Outdated"];
cell.badgeText = [NSString stringWithFormat:#"Update"];
cell.badgeColor = [UIColor orangeColor];
}else if ([fileStatus isEqualToString:#"updated"]){
cellLabel = [NSString stringWithFormat:#"%# (%#)",cellLabel,#"Latest"];
}
UIFont *font1 = [UIFont fontWithName:#"Century Gothic" size:15.0f];
cell.textLabel.font=font1;
//if there is no file user can not tocuh the row
if ([name length]==0) {
cell.userInteractionEnabled = NO;
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = description;
}else{
//set cell title
cell.textLabel.text = cellLabel;
}
//set row images
if ([name rangeOfString:#"docx"].location != NSNotFound) {
cell.imageView.image= docImage;
}else if ([name rangeOfString:#"xlsx"].location != NSNotFound){
cell.imageView.image= xlsImage;
}
else if ([name rangeOfString:#"pdf"].location != NSNotFound){
cell.imageView.image= pdfImage;
}
else if ([name rangeOfString:#"ppt"].location != NSNotFound){
cell.imageView.image= pptImage;
}
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"rounded corner box center#2x.png"]];
// At end of function, right before return cell
cell.textLabel.backgroundColor = [UIColor clearColor];
NSLog(#"%#",cell.textLabel.text);
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];.0
*/
NSLog(#"didselect row is called %d",indexPath.row);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[DBSession sharedSession] isLinked]) {
if([[segue identifier] isEqualToString:#"pushDocumentView"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSInteger section =[indexPath section];
NSInteger row = [indexPath row];
NSString *fileName = [[self agenda] getFileNameWithSection:section Row:row];
NSDictionary * agendaDic = [[[self agenda]revision] objectForKey:fileName];
NSString *fileStatus =[agendaDic objectForKey:#"status"];
DocumentViewController *docViewController = [segue destinationViewController];
//This will display on the Document Viewer
docViewController.fileName=fileName;
//This will determine remote or local copy display
docViewController.fileStatus=fileStatus;
}
}else {
[self displayError];
[self setWorking:NO];
}
}
Just called a perfromseguewith Identifier
because this is called - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender also when you call [self performSegueWithIdentifier:#"yoursegue" sender:self];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];.0
*/
[self performSegueWithIdentifier:#"yoursegue" sender:self];
NSLog(#"didselect row is called %d",indexPath.row);
}

UITableView displays data then crashes

I'm making an iOS that lists the files in the Documents dictionary. I want to display this data in a UITableView, the problem is that it's not working.
It loads the data in to the view. Then the application freezes and calls EXC_BAD_ACCESSThis is my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
timesRun = 0;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectoryPath error:nil];
[bundleRoot release];
NSLog(#"Count: %i",[dirContents count]);
return [dirContents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableViewData cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
int Locatation = indexPath.row;
Locatation++;
cell = [tableViewData dequeueReusableCellWithIdentifier:#"MyCells"];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"]autorelease];
}
//cell.textLabel.text = [NSString stringWithFormat:#"Cell: %i",Locatation];
cell.textLabel.text = [dirContents objectAtIndex:timesRun];
timesRun++;
return cell;
NSLog(#"Did return");
}
- (void)tableView:(UITableView *)tableViewDat didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"%#",cell.textLabel.text);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This displays a basic misunderstanding of the concept of the table view data source.
My suggestion:
Create an array that contains the files outside any tableview methods. Then you use that array to feed the tableview.
Use array.count to return numberofrowsatindexpath.
Also, on providing the cells at cellforrowatindexpath, don't use iterations/counters. The tableview ask for each element of your array itself using the indexpath argument. You access it like this:
id object = [array objectArIndex: indexPath.row]
And you then use the objects attributes to set the labels of the cell.
Please read a tutorial on tableviews. I recommend itunesU Paul hegarty's lectures. They're really great.
Ps. You release the bundleRoot object in numberofrowsinsection, which you don't retain (or use at all) which is most likely causing your crash.
Edit:
With a little more spare time, I retouched your code:
//code not tested/written in xcode. Might contain typos
//in your .m file
//in your (private) interface
#property (nonatomic, retain, readonly) NSArray *dirContents;
//in your implementation
#synthesize dirContents=_dirContents;
-(NSArray*) dirContents {
if (!dirContents) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
_dirContents = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectoryPath error:nil] retain];
}
return _dirContents;
//note that if you want to "refresh" the contents you would have to
//release _dirContents and set it to nil or implement this differently
}
-(void) dealloc {
[_dirContents release];
//....
[super dealloc];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[self dirContents] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCells"];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCells"]autorelease];
}
cell.textLabel.text = [[self dirContents] objectAtIndex: indexPath.row];
return cell;
//  NSLog(#"Did return"); //this never gets called by the way
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"%#",cell.textLabel.text);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
My problem was sort of like Mario's answer. [dirContents count] returned a higher value than the amount of times it could add an object from the array.In other words it was a Out of Bounds error.
Make sure you are not releasing dirContents while using that.I am sure you are not doing but just cross check with your code.

table view use customized cell file and how ot use segue

I user Master-Detail created a project. On the MasterViewController, the table cell i use a MasterCell.h and MasterCell.m to build my customized cell, so my code is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MasterCell *cell = (MasterCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[MasterCell alloc] initWithFrame:CGRectZero];
NSString *value = [[myContacts objectAtIndex:indexPath.row] valueForKey:#"Name"];
cell.nameContentLabel.text = [NSString stringWithFormat:#"%#", value];
value = [[myContacts objectAtIndex:indexPath.row] valueForKey:#"Tele"];
cell.teleContentLabel.text=[NSString stringWithFormat:#"%#", value];
value = [[myContacts objectAtIndex:indexPath.row] valueForKey:#"Image"];
cell.myImageView.image = [[UIImage alloc] initWithContentsOfFile:value];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
And whan i want click the cell and push the DetailViewController, so my stroyboard is use the origin creat segue, but it didn't work, i think the segue is not my MasterCell, and i had try to change the storyboard cell custom Class, and it was't not success.How do I do? Thanks.
In your storyboard you should create segue not from cell, but from entire UITableViewController and set some identifier, for example "MySegue" and style is "Push".
Then in your tableViewController you should add
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"MySegue" sender:self];
}
and
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"MySegue"]){
//do your stuff
}
}