display image cell in tableview - objective-c

I tried to display imagecells in tableview, but the program crashes..
here's my imageCell class:
#interface ImageCell : NSTextFieldCell {
NSImage *imageIcon;
NSString *labelStr;
}
#property (retain) NSImage *imageIcon;
#property (retain) NSString *labelStr;
- (id) initWithLabel:(NSString *) labelString imageName:(NSString *) imageString;
when the program runs, it crashes with error message:
-[NSTextFieldCell labelStr]: unrecognized selector sent to instance 0x10011f160
but I already provide my own imageCell class...
is there anything I did wrong, thanks!!!
here's my tableview delegate & datasource:
- (void) awakeFromNib {
self.list = [[NSMutableArray alloc] init];
[self.list addObject:[[ImageCell alloc] initWithLabel:#"Library" imageName:#"album.tiff"]];
// set first cell here
NSTableColumn *col = [[self.tableView tableColumns] objectAtIndex:0];
[col setDataCell:[list objectAtIndex:0]];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)pTableView {
return [self.list count];
}
- (id)tableView:(NSTableView *)pTableView objectValueForTableColumn:(NSTableColumn *)pTableColumn row:(int)pRow {
ImageCell *imageCell = (ImageCell *)[self.list objectAtIndex:pRow];
return imageCell.labelStr;
}
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)pRow {
ImageCell *imageCell = (ImageCell *)cell;
imageCell.image = [[self.list objectAtIndex:pRow] imageIcon];
[imageCell setTitle:imageCell.labelStr];
}

The docs don't specify any guarantee that the table columns returned by -tableColumns are in any particular order. Try asking for -tableColumnWithIdentifier: (and make sure your table columns have identifiers specified in the nib).

Related

Hiding an autocomplete UITableView that was created programmatically

I'm building an application with an autocomplete UITableView from this tutorial. I have the autocomplete functionality working properly, but I would like the UITableView-autocomplete drop down to disappear when the word is clicked on or when it is touched up outside. I'm not sure how to set up a delegate when the object is set up programmatically. I've only done this using the interface builder.
.h
#interface slrpViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
{
NSMutableArray *dataArray;
NSMutableData *receivedData;
NSMutableArray *pastUrls;
NSMutableArray *autocompleteUrls;
UITableView *autocompleteTableView;
}
#property(nonatomic, retain) IBOutlet UITextField *eWordEntered;
#property (nonatomic, retain) NSMutableArray *pastUrls;
#property (nonatomic, retain) NSMutableArray *autocompleteUrls;
#property (retain, nonatomic) NSMutableData *responseData;
#property (nonatomic, retain) UITableView *autocompleteTableView;
-(void)setReceivedData:(NSMutableData*)pReceivedData;
-(NSMutableData *) getReceivedData;
-(void) getAutoCompleteArray;
-(void)searchAutocompleteEntriesWithSubstring:(NSString *)substring;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self getAutoCompleteArray];
pastUrls = [[NSMutableArray alloc] init];
NSLog(#"In the viewDidLoad and pasturl is: %#", self.pastUrls);
self.autocompleteUrls = [[NSMutableArray alloc] init];
autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(210, 225, 310, 120) style:UITableViewStylePlain];
self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
[self.view addSubview:autocompleteTableView];
-(void)setReceivedData:(NSMutableData*)pReceivedData
{
receivedData = pReceivedData;
}
-(NSMutableData *) getReceivedData{
return receivedData;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *e = nil;
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: receivedData options: NSJSONReadingMutableContainers error: &e];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:receivedData
options:kNilOptions
error:&error];
seneca_word.ids = [jsonDict objectForKey:#"ids"];
NSArray *array_ids = [jsonDict objectForKey:#"ids"];
NSString *ids = array_ids[0];
seneca_word.ids = ids;
for (id key in jsonDict)
{
NSLog(#"key: %#, value: %#", key, [jsonDict objectForKey:key]);
NSLog(#"The value of bases by itself is: %#", [jsonDict objectForKey:#"bases"]);
}
if (!jsonArray)
{
NSLog(#"Error parsing JSON: %#", e);
}
else
{
if([jsonDict objectForKey:#"english"] != nil){
pastUrls = [jsonDict objectForKey:#"bases"];
}
else{
//Some of JSON object that I don't want to use here
}//else
}//(void)connectionDidFinishLoading
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {
[autocompleteUrls removeAllObjects];
for(NSString *curString in pastUrls) {
NSRange substringRange = [curString rangeOfString:substring];
if (substringRange.location == 0) {
[autocompleteUrls addObject:curString];
}
}
[autocompleteTableView reloadData];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
autocompleteTableView.hidden = NO;
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return autocompleteUrls.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];
}
cell.textLabel.text = [autocompleteUrls objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
self.eWordEntered.text = selectedCell.textLabel.text;
if(tableView == autocompleteTableView){
//The autocomplete table view is the one that fired the didSelect delegate method
//So hide the autocomplete table.
//do whatever else you need to do to empty the autocompleteTableView's data source
//or/and simply hide the table after that
[autocompleteTableView setHidden:YES];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//When the user clicks outside of the uitableview it will disappear
[autocompleteTableView setHidden:YES];
}
As you can see I populate the autocomplete UITableView with JSON data that I'm getting from a RESTful API.
I'm getting the warning, Assigning to 'id<UITableViewDelegate>' from incompatible type 'ViewController *const __strong' for the lines:
self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;
I imagine once I get the delegate stuff sorted out I'll be able to do what I want. I did some research and tried to create a delegate class but wasn't able to get that solution working. I'm not even sure if that's the right way to go about this as I usually do this stuff by interface builder and not programmatically. Any direction or help is greatly appreciated. Thanks!
You should be using the tableView's didSelectCellAtIndexPathRow delegate method to identify user taps on a cell from a tableView. It's ok if you created your tableView progammatically.
Simply make sure the UIViewController conforms to the UITableViewDelegate and UITableViewDataSource` protocols.
make sure you set the tableView's delegate and dataSource property to self.
Implement the didSelectCellAtIndexPathRow delegate method in your viewController's .m file like so:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
Then inside that delegate method you need to help detect from which tableView your didSelect method got fired from as you only want to hide the autocomplete table when the user selects a cell from that table. So you do a simple tableView check like so:
if(tableView == autocompleteTableView){
//The autocomplete table view is the one that fired the didSelect delegate method
//So hide the autocomplete table.
//do whatever else you need to do to empty the autocompleteTableView's data source
//or/and simply hide the table after that
[autocompleteTableView setHidden:YES];
}
You probably also want to make sure that you set the autocompleteTableView hidden property to NO when the user types in something in the textfield so that the auto complete can show appear again.
And thats all buddy.
try setting self.autocompleteTableView.hidden = YES;

Create an array of custom Object to fill it and take his content to fill a UITableView

I have a Class called Product that contains some propeties, I wanna make that my class will be the base for an list of Product called Products. And this list can access in a UITableView to fill it with the content of Products.
Also, the content of each product will be filled by a web service.
My code is:
#interface Product : NSObject
{
int identifier;
NSString* title;
NSString* quantity;
float price;
UIImage* image;
}
#property (nonatomic, assign) int identifier;
#property (nonatomic, retain) NSString* title;
#property (nonatomic, retain) NSString* quantity;
#property (nonatomic, assign) float price;
#property (nonatomic, retain) UIImage *image;
-(id)initWithProduct:(int) identifier withTitle:(NSString*)title numberUses:(NSString*)uses withPrice:(float)price withImage:(UIImage*)image;
#end
With his .m
#implementation Product
#synthesize identifier = _identifier;
#synthesize title = _title;
#synthesize price = _price;
#synthesize quantity = _quantity;
#synthesize image = _image;
- (void)dealloc {
NSLog(#"article dealloc \n");
[self.title release];
[self.quantity release];
[self.image release];
[super dealloc];
}
- (id)init {
self = [super init];
if(self) {
self.title = [[[NSMutableString alloc] init] autorelease];
self.identifier = 0;
self.price = 45.0;
self.quantity = [[[NSMutableString alloc] init] autorelease];
self.image = [[[UIImage alloc] init] autorelease];
}
return self;
}
-(id)initWithProduct:(int) inIdentifier withTitle:(NSString*)inTitle numberUses:(NSString*)inQuantity withPrice:(float)inPrice withImage:(UIImage*)inImage
{
self = [super init];
if (self) {
if (title!= nil) {
self.title = inTitle;
}
if (quantity!= nil) {
self.quantity = inTitle;
}
if (image!= nil) {
self.title = inTitle;
}
self.price = inPrice;
self.identifier = inIdentifier;
}
return self;
}
#end
My UITableView header is:
#interface TableView : UIViewController
< UITableViewDataSource
, UITableViewDelegate
>{
NSMutableArray *products;
}
in the m. I have:
EDIT
Now the Title of my cell is shows as (null)
- (void)viewDidLoad
{
[super viewDidLoad];
products = [[NSMutableArray alloc] init];
[products addObject:[[Product alloc] initWithProduct:1 withTitle:#"df" numberUses:#"dsf" withPrice:12.3 withImage:[UIImage imageNamed:#"btn_invite"]]];
[products addObject:[[Product alloc] initWithProduct:1 withTitle:#"2" numberUses:#"dsf" withPrice:12.3 withImage:[UIImage imageNamed:#"btn_invite"]]];
[products addObject:[[Product alloc] initWithProduct:1 withTitle:#"4" numberUses:#"dsf" withPrice:12.3 withImage:[UIImage imageNamed:#"btn_invite"]]];
[products addObject:[[Product alloc] initWithProduct:1 withTitle:#"4" numberUses:#"dsf" withPrice:12.3 withImage:[UIImage imageNamed:#"btn_invite"]]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Controller *cell = (Controller*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSString* nameNib = UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM() ? #"Controller" : #"ControllerIph";
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nameNib owner:self options:nil];
cell = [nib objectAtIndex:0];
}
Product* obj = [products objectAtIndex:indexPath.row];
cell.title.text = [NSString stringWithFormat:#"%#", obj.title];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 4;
}
Thanks in advance!
Not an answer to your question, but a few comments regarding your code:
You have 4 memory leaks when you add the 4 new instances of Product to your array. The array retains the objects you add to it, so you should autorelease the Product instances when you add them.
In dealloc you should say self.title = nil instead of [self.title release]. Although your version works, it leaves you with instance variables that contain references to deallocated objects (= dangling pointers). Because this happens in dealloc and the Product object is going away soon, it won't hurt you now, but you will get bitten at some point in the future if you keep to this style.
You don't need to declare the instance variables, and you don't need to synthesize the properties. The compiler does all this for you.
In initWithProduct you must not check things like if (title!= nil) - just say self.title = inTitle straightaway. After all, initWithProduct is an initializer just like init, so title cannot contain anything at this point.
Hope this helps.
EDIT
Actually, the last point is probably why you see "(null)" for the title of your cells. Your check if (title!= nil) is never true because the instance variable title is nil during the initializer, so the assignment self.title = inTitle never happens.
In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath you do not initialize cells for your TableView. Add the below code to this method before the code that you already have
static NSString *CellIdentifier = #"Cell Identifier";
UITableViewCell *cell;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
and make sure you return cell; at the end of that method
Also make sure you implement the rest of the necessary TableView delegate methods:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

Add NSTableView data to NSPopUpButton items

I have a NSTableView where items can be added and deleted. Once items have been added to the table, I would like those items to also show as items for an NSPopUpButton. I tried the addItemsWithTitles: method but it gives me an error.
#import "TableController.h"
#import "Favorites.h"
#interface TableController ()
#property NSMutableArray *array;
#property (weak) IBOutlet NSTableView *tableView;
#property (weak) IBOutlet NSPopUpButton *popButton;
#end
#implementation TableController
- (id)init {
self = [super init];
if (self) {
_array = [[NSMutableArray alloc] init];
}
return self;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [_array count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
Favorites *fav = [_array objectAtIndex:row];
NSString *ident = [tableColumn identifier];
return [fav valueForKey:ident];
}
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
Favorites *fav = [_array objectAtIndex:row];
NSString *ident = [tableColumn identifier];
[fav setValue:object forKey:ident];
}
- (IBAction)add:(id)sender {
[_array addObject:[[Favorites alloc] init]];
[_tableView reloadData];
[_popButton addItemsWithTitles:_array];
}
-(IBAction)delete:(id)sender {
NSInteger row = [_tableView selectedRow];
[_tableView abortEditing];
if (row != -1) {
[_array removeObjectAtIndex:row];
}
[_tableView reloadData];
}
#end
So I tried logging the objectAtIndex:0 for the array and didn't get a string but received some numbers instead:
Array string is <Favorites: 0x10013e820>
And also for reference my Favorites class is
#import "Favorites.h"
#interface Favorites ()
#property (copy) NSString *location;
#end
#implementation Favorites
- (id)init {
self = [super init];
if (self) {
_location = #"City, State or ZIP";
}
return self;
}
#end
Your array has instances of your class, Favorites, and in your addItemsWithTiles: method you are adding those instances, not some string property of those instances, which is what I presume you want. If you use [_array valueForKey:#"whateverKeyHasYourStrings"] as the argument to addItemsWithTitles: instead of just _array, I think it will work ok.

Search in UITableView - NSInvalidArgumentException error

I'm implementing the search bar in a UITableView (tblFriends) with a "SearchBar and search Display controller"
This is my NSarray of dictionaries filteredFriendsList (equal to friendsList NSarray):
{
gender
id
name
picture
}
I have the table view in a UIViewController, (not in a tableViewController) because the table occupies only half view.
This is the code:
INTERFACE:
#import <UIKit/UIKit.h>
#import "ClasseSingleton.h"
#import "FBConnect.h"
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *friendsList;
NSDictionary *friendsDict;
NSMutableArray *filteredFriendsList;
IBOutlet UITableView *tblFriends;
}
#property (nonatomic, retain) NSArray *friendsList;
#property (nonatomic, retain) NSMutableArray *filteredFriendsList;
-(void)getFriends;
#end
IMPLEMENTATION
#import "ViewController.h"
#implementation ViewController
#synthesize friendsList, filteredFriendsList;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[tblFriends setDelegate:self];
[tblFriends setDataSource:self];
}
- (void)getFriends{
NSLog(#"ENTRATO - getFriends");
//Copy ARRAY in other ARRAY
friendsList = [NSArray arrayWithArray:[ClasseSingleton getFriends]];
filteredFriendsList = [NSArray arrayWithArray:[ClasseSingleton getFriends]];
NSLog(#"getFriends : DESCRIPTION\n\n %#", [friendsList description]);
NSLog(#"Count friendslist: %i", [friendsList count]);
[tblFriends reloadData];
}
// *****TABLE MANAGEMENT***** //
//Nuber of cells
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"tabella1");
return [filteredFriendsList count];
}
//Populate the table
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPat{
static NSString * cellIdentifier = #"cell";
//Set Style cell
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
friendsDict = [filteredFriendsList objectAtIndex:indexPat.row];
//Set CELL TEXT
NSString *cellValue = [friendsDict objectForKey:#"name"];
NSLog(#"TBL %#", cellValue);
[cell.textLabel setText:cellValue];
return cell;
}
// SEARCH IN TABLE
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)saearchBar {
[self.filteredFriendsList removeAllObjects];
[self.filteredFriendsList addObjectsFromArray: friendsList];
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
/*
Update the filtered array based on the search text and scope.
*/
[self.filteredFriendsList removeAllObjects]; // First clear the filtered array.
/*
Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
*/
NSString *cellTitle;
for (cellTitle in friendsList){
// for (cellTitle in [friendsDict objectForKey:#"name"]){
NSComparisonResult result = [cellTitle compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame){
[filteredFriendsList addObject:cellTitle];
}
}
}
...
#end
Everytime i put some character in the search bar the app crashes with this error:
'NSInvalidArgumentException', reason: '-[__NSCFDictionary compare:options:range:]: unrecognized selector sent to instance
I hope to solve the problem, it's the 6th days with this error.
Thank you.
You declare filteredFriendsList to be a NSMutableArray, but you're assigning an immuatble NSArray to it here:
filteredFriendsList = [NSArray arrayWithArray:[ClasseSingleton getFriends]];
Change it to this:
filteredFriendsList = [NSMutableArray arrayWithArray:[ClasseSingleton getFriends]];

NULL elements in NSMutableArray

I have a problem...
IN my MuttableArray have N element, but all elements is null
.h
#interface ViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> {
NSMutableArray *listProjectPost;
}
#property (retain,nonatomic) NSMutableArray *listProjectPost;
.m
#implementation ViewController
#synthesize listProjectPost;
-(void)dealloc
{
[self.listProjectPost release];
[super dealloc];
}
-(void)viewWillAppear:(BOOL)animated{
self.listProjectPost = [NSMutableArray array];
// loop code
// current element
currentNews *dop = [[currentNews alloc] init];
[self.listProjectPost addObject:[dop createElement:node]];
[dop release];
}
in
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
currentNews *dop = [self.listProjectPost objectAtIndex:indexPath.row];
cell.textLabel.text = [dop getTitle];
...
}
all ok in top view (view when creating)
but next index i have error - EXC_BAD_ACCESS
sorry for my english
If you need to store a null value in an Objective-C array, use [NSNull null]. You should check [drop createElement:node] to see if it is nil before adding it to your array.