I'm trying to show some content in my NSTableView in my mac app.
#implementation OpenTasksViewController {
NSMutableArray *tasks;
}
- (id)init {
self = [super init];
if (self) {
tasks = [NSMutableArray array];
[tasks addObject: [[Task alloc] initWithTitle:#"HI"]];
}
return self;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [tasks count];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTableCellView *cell = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
Task *t = [tasks objectAtIndex:row];
cell.textField.stringValue = t.title;
return cell;
}
This class implements the NSTableViewDataSource and NSTableViewDelegate protocols.
Sadly, my app doesn't show the content.
I tried using reloadData, but that didn't work either.
When I debug into the project, the stringValue of cell.textField is correct.
Related
enter code here[youtube picture of the same code][1]I keep getting an error with my code where it says
"unexpected "#" in program and also missing "#end"
If you look at the code below the #end is there but however much I retype it the answer is the same "missing #end"
Here is the full code
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
-(NSMutableArray *) objects
{
if (!_objects){
_objects =[[NSMutableArray alloc]init];
}
return _objects;
}
-(NSMutableArray *) results
{
if (!_results) {
_results =[[NSMutableArray alloc]init];
}
return _results;
}
-(void)viewDidLoad
{
[super viewDidLoad];
[self.objects addObject:#"Tabebuia yellow"];
[self.objects addObject:#"Prunus armeniaca"];
[self.objects addObject:#"Tabebuia rosea"];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) searchThroughData
{
self.results= nil;
NSPredicate * resultsPredicate = [NSPredicate predicateWithFormat:#"SELF contains [search]%#", self.searchBar.text];
self. results = [[ self.objects filteredArrayUsingPredicate:resultsPredicate]mutableCopy];
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self searchThroughData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView)
{
return self.objects.count;
}else{
[self searchThroughData];
return self.results.count;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (tableView == self.tableView){
cell.textLabel.text = self.objects[indexPath.row];
} else {
cell.textLabel.text = self.results[indexPath.row];
}
return cell;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.searchController.isActive)
{
[self performSegueWithIdentifier:#"Showdetail" sender:self];
}
-(void) PrepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender
if ([[ segue identifier] isEqualToString:#"ShowDetail"]) {
NSString *object = nil;
NSIndexPath *Indexpath = nil;
if (self.UISearchController.isActive)
{UISearchController
Indexpath = [[ self.searchController searchResultsTableView]indexPathForSelectedRow];
object = self.results [Indexpath.row];
}else{
Indexpath = [self.tableView indexPathForSelectedRow];
object = [[self.objects [Indexpath.row];
[segue destinationViewController] setDetailLabelContents:object];
}}
#end
You have no closing } at the end of the prepareForSegue:sender: method. Formatting and indenting properly makes this clear.
You have code just floating outside of a method (the lines before the tableView:didSelectRowAtIndexPath: method.
There needs to be a proper pairing of { and } and code needs to be inside methods or functions.
I am trying to add Search to Todo demo application. I have below code so far with Search working. The issue with below code is that the Pagination doesn't work anymore. There is simlilar question about pagination but when "number of rows in section + 1" returned, the app crashes with [__NSArrayM objectAtIndex:] error. How do I get the Pagination working?
// MyTableController.h
#import <Parse/Parse.h>
#interface MyTableController : PFQueryTableViewController
#end
// MyTableController.m
#import "MyTableController.h"
#interface MyTableController() <UISearchDisplayDelegate> {
}
#property (nonatomic, strong) UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#end
#implementation MyTableController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
self.className = #"Todo";
self.keyToDisplay = #"text";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 5;
}
return self;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar
contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
CGPoint offset = CGPointMake(0, self.searchBar.frame.size.height);
self.tableView.contentOffset = offset;
self.searchResults = [NSMutableArray array];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: self.className];
[query whereKey:#"text" containsString:searchTerm];
NSArray *results = [query findObjects];
[self.searchResults addObjectsFromArray:results];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count ;
}
}
#pragma mark - Parse
- (void)objectsDidLoad:(NSError *)error {
[super objectsDidLoad:error];
}
- (void)objectsWillLoad {
[super objectsWillLoad];
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.className];
if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByAscending:#"priority"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [object objectForKey:#"text"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Priority: %#", [object objectForKey:#"priority"]];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
#end
In your own implementation of numberOfRowsInSection you must return numberOfRows + 1. But then you must write your code considering you have more cells than query returning. Check out your heightForRowAtIndexPath and others methods: there can be calls to [self.objects objectAtIndex:self.objects.count]. I mean, if indexPath.row == self.objects.count, its a "Load More" cell.
If you overriding willSelectRowAtIndexPath or didSelectRowAtIndexPath, you must do this in the top of method
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
or add this (previous case is prefered)
if (indexPath.row == self.objects.count)
{
[self loadNextPage];
}
Customization of Load More cell placed in -(PFTableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath
And im using
-(PFTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath
instead of
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
I am creating a Two Level table view. And the second view is supposed to have the list of the movies I have listed below in my viewDidLoad method, but it is not showing.(You can see my screen shots attached)Does anyone know which file where I can look to see why it is not showing? The code below is from my DisclosureButtonController.m file which is to display this information after I hit the Disclosure Buttons instance on the First Level screen.
Regards,
#import "LWWDisclosureButtonController.h"
#import "LWWAppDelegate.h"
#import "LWWDisclosureDetailController.h"
#interface LWWDisclosureButtonController ()
#property (strong, nonatomic) LWWDisclosureDetailController *childController;
#end
#implementation LWWDisclosureButtonController
#synthesize list;
#synthesize childController;
//- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
//{
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
//if (self) {
// Custom initialization
//}
//return self;
//}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *array = [[NSArray alloc] initWithObjects:#"Toy Story", #"A Bug's Life", #"Toy Story 2", #"Monsters, Inc.", #"Finding Nemo", #"The Incredibles", #"Cars", #"Ratatouille", #"WALL-E", #"Up", #"Toy Story 3", #"Cars 2", #"Brave", nil];
self.list = array;
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.list = nil;
self.childController = nil;
// Release any retained subviews of the main view.
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [list count];//
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString * DisclosureButtonCellIdentifier = #"DisclosureButtonCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DisclosureButtonCellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:DisclosureButtonCellIdentifier];
}
NSUInteger row = [indexPath row];
NSString *rowString = [list objectAtIndex:row];
cell.textLabel.text = rowString;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hey, boss do you see the disclosure button?" message:#"If you're trying to drill down, touch that instead mate!" delegate:nil cancelButtonTitle:#"Won't happen again" otherButtonTitles:nil];
[alert show];
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *)indexPath
{
if (childController == nil)
{
childController = [[LWWDisclosureDetailController alloc]initWithNibName:#"LWWDisclosureDetail" bundle:nil];
}
childController.title = #"Disclosure Button Pressed";
NSUInteger row = [indexPath row];
NSString *selectedMovie = [list objectAtIndex:row];
NSString *detailMessage = [[NSString alloc]initWithFormat:#"You pressed the disclosure button for %#.", selectedMovie];
childController.message = detailMessage;
childController.title = selectedMovie;
[self.navigationController pushViewController:childController animated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Why not start the array with the VC instead of after the VC loads? Try overriding the init method.
- (id) init {
if((self == [super init])) {
//load your array here and set
}
return self;
}
That way, on older devices, you don't have to wait after the view loads to see the array. But, however, this is my preference. I love to override init methods and create my own.
Also, for some weird reason on my SDK, I have to use NSMutableArray instead of NSArray or it won't work. Maybe you have the same issue?
Also, I've noticed NSString *selectedMovie. Instead of using just "row", use the getter indexPath.row.
Hope these suggestions helped!
Call:
[self.tableView reloadData]; (put in place of self.tableView the var or property connected to the tableView)
after the:
self.list = array;
code line in the viewDidLoad method
and put a
NSLog(#"number of rows: %d", [self.list count]);
in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [list count];//
}
to check if it is not zero.
I have written the following code for a FirstLevelController implementation file, but the Disclosure Buttons, icons don't display in the view. Have checked the code, but can't figure out what's wrong.
FirstLevelController.m:
#import "BiDFirstLevelController.h"
#import "BidSecondLevelController.h"
#import "BiDDisclosureButtonController.h"
#implementation BiDFirstLevelController
#synthesize controllers;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"First Level";
NSMutableArray *array = [[NSMutableArray alloc]init];
// Disclosure button
BiDDisclosureButtonController *disclosureButtonController = [[BiDDisclosureButtonController alloc]initWithStyle:UITableViewStylePlain];
disclosureButtonController.title = #"Disclosure Buttons";
disclosureButtonController.rowImage = [UIImage imageNamed:#"disclosureButtonControllerIcon.png"];
[array addObject:disclosureButtonController];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.controllers = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.controllers count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstLevelCell = #"FirstLevelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstLevelCell];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstLevelCell];
}
// Configure the cell...
NSUInteger row = [indexPath row];
BiDSecondLevelController *controller = [controllers objectAtIndex:row];
cell.textLabel.text = controller.title;
cell.imageView.image = controller.rowImage;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
BiDSecondLevelController *nextController = [self.controllers objectAtIndex:row];
[self.navigationController pushViewController:nextController animated:YES];
}
#end
Your implementation of numberOfSectionsInTableView: returns 0, which means the table view should always be empty. Since returning 0 from this method doesn't make sense, I guess it's a typo.
I have a UITableView in my UITableViewController (lol, obviously) but I need to get a cell at a given index inside the - (void)viewWillAppear:(BOOL)animated method.
Now, my cells are static and I create them in the interface builder. If I call
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:previously_selected_cell.integerValue inSection:0]];
it returns null for the cell. I only have 3 static cells in 1 sections. I tried both sections 0 and 1 and both return null.
Currently I have removed the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method because if I add it, it will clear the UITableView of all my static cells.
Is there a method I can call in - (void)viewWillAppear:(BOOL)animated that will return a cell at a given index?
Thanks in advance!
EDIT: I checked out this stackoverflow question but I'm using static cells without cellForRowAtIndexPath so that question didn't help. :(
EDIT2: I'm trying to set the accessory type of the cell when the view loads. But only on a certain cell, that cell being the one the user selected before he quit the app.
#import "AutoSyncSettings.h"
#import "CDFetchController.h"
#implementation AutoSyncSettings
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSArray *objects = [results fetchedObjects];
NSNumber *sync_setting;
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
sync_setting = [object valueForKey:#"wifi_setting"];
NSLog(#"(Settings)sync_setting: %#",sync_setting);
NSLog(#"(Settings)sync_setting int value: %i",sync_setting.integerValue);
NSLog(#"(Settings)TableView: %#",self.tableView);
//cell is null, even after this.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:wifi_settings.integerValue inSection:0]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//cell is still null. WHY OH WHY? :(
objects = nil;
}
cdfc = nil;
results = nil;
objects = nil;
sync_setting = nil;
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (int i = 0; i < [tableView numberOfRowsInSection:indexPath.section]; i++)
{
if([[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]] accessoryType] == UITableViewCellAccessoryCheckmark)
{
[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]].accessoryType = UITableViewCellAccessoryNone;
}
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSManagedObjectContext *context = [results managedObjectContext];
NSArray *objects = [results fetchedObjects];
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
else
{
//INSERT NEW OBJECT
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"SETTINGS" inManagedObjectContext:context];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
}
#end
I have a project doing exactly this and it works perfectly. However, it doesn't work unless you call [super viewWillAppear:animated] before trying to access the cells in this manner.
The base implementation presumably loads in the cells from the storyboard.
I want to add a checkmark accessory to the previously selected cell,
the previously_selected_cell variable gets stored even if the app
quits/crashes
The way to go will be to control the indexPath in your cellForRowAtIndexPath implementation and act if it's equal to previously_selected_cell.integerValue:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// usual cache lookup, allocation of the cell, etc
if (indexPath.row == previously_selected_cell.integerValue) {
// add checkbox here
} else {
// remove checkbox
}
}