XIB backed View with Subclassing - iphone

I have a UITableViewCell defined in a XIB (with outlets setup) and the custom class set to 'CustomTableViewCell'. I'm now looking to subclass the 'CustomTableViewCell' with a 'SubclassCustomTableViewCell', however I'd like to use the same XIB (and not need to redefine my view. Is this possible? I currently have:
+ (SubclassCustomTableViewCell *)create
{
// Create undefined cell.
id cell = nil;
// Iterate over NIB and find a matching class.
NSBundle *bundle = [NSBundle mainBundle];
NSArray *cells = [bundle loadNibNamed:#"CustomTableViewCell" owner:nil options:nil];
for (cell in cells) if ([cell isKindOfClass:[self class]]) break;
// Return cell.
return cell;
}
But I can't figure out to to get it to return anything but the parent.

+ (SubclassCustomTableViewCell *)create
{
// Create undefined cell.
id cell = nil;
// Iterate over NIB and find a matching class.
NSBundle *bundle = [NSBundle mainBundle];
NSArray *cells = [bundle loadNibNamed:#"CustomTableViewCell" owner:nil options:nil];
for (cell in cells) if ([cell isKindOfClass:[self class]]) return cell; //change this
// Return cell.
return nil; //change this
}
could you tell me where + (SubclassCustomTableViewCell *)create is defined, in which class

Related

adding property to UITableView subclass

i'm creating UITableViewCell subclass which need to hold 3 types of images: facebook twitter and linkedin. the thing is that i need to know which service the cell support at the moment so i have try to add a property to the class called service which is NSString.
this is how i am setting up my cell to ad it to the table:
static NSString *sCellIdentifier = #"sCell";
SocialTableViewCell *sCell = [tableView dequeueReusableCellWithIdentifier:sCellIdentifier];
sCell.service = #"service";
if (sCell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ExampleView" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[SocialTableViewCell class]])
{
sCell = (SocialTableViewCell *)currentObject;
break;
}
}
}
if (indexPath.row == 0) {
sCell.serviceImage.image = [UIImage imageNamed:#"icon_Twitter.png"];
sCell.service = #"twitter";
return sCell;
}
i am trying to set the property like this :
sCell.service = #"twitter";
and when i am trying to read it from the awakeFromNib method in the SocialTableViewCell class i get null. what should i do to manage this?
The awakeFromNib method is called before you have set the service property.
You could use the setter method of the service property :
-(void) setService:(NSString *)service {
// Set the value to the internal iVar
_service = service;
// Here you can do what you want with the service value like
self.titleLabel.text = service;
}

Determine different cells for iPhone and iPad in tableView:cellForRowAtIndexPath:

I just try to create an app for iPhone and iPad. For this i created a tableview that creates cells expecting the json that will be received when the app is loading. Inside the method
tableView:cellForRowAtIndexPath:
I initiate the cell that will be used for the iPhone and I set the specific values from the json. The cell I use is a custom Cell i created with a new object and NIB-File. The code looks like this:
static NSString *CellIdentifier = #"tvChannelIdentifier";
tvChannelCell *cell = (tvChannelCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"tvChannelCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
....
Now that I try to make the app work on the iPad too, I created a new custom cell, also with a new object and a NIB-File. The names of the variables are the same as in the customIPhoneCell so that I don't have to change the whole code. I just inserted a switch inside the tableView:cellForRowAtIndexPath: so that i show the right cell but it can't be accessed by the code:
static NSString *CellIdentifier = #"tvChannelCell";
static NSString *IPadCellIdentifier = #"tvChannelIPadCell";
//determination which device ---> choose cell
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
tvChannelCell *cell = (tvChannelCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}else{
tvChannelIPadCell = (tvChannelIPadCell *) [tableView dequeueReusableCellWithIdentifier:IPadCellIdentifier];
}
I tried to define the cell objects at the top of the class but then i can't use the same variable name. I also tried to choose the NIB file of the iPad to check if it'll be displayed but nothing happens. And I tried to set an UITableviewcell at the top,
UITableViewCell *cell
and set the specific cell type inside my switch in cellForRowAtIndexPath but then the variables can't be accessed.
So my question is, is it possible to do this switch inside the tableview method or do i have to code to several parts for each device where each celltype has its own variablename?
What I do:
I create only one UITableViewCell subclass with 2 xibs, one xib for iPad and another for iPhone.
tvChannelCell *cell = (tvChannelCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
nib = [[NSBundle mainBundle] loadNibNamed:#"tvChannelCell_iPhone" owner:self options:nil];
}else{
nib = [[NSBundle mainBundle] loadNibNamed:#"tvChannelCell_iPad" owner:self options:nil];
}
cell = [nib objectAtIndex:0];
}
this line of code useful for differenciating iphone and ipad,
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
tvChannelCell *cell = (tvChannelCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}else{
cell = (tvChannelIPadCell *) [tableView dequeueReusableCellWithIdentifier:IPadCellIdentifier];
}
It's quite simple, why don't you create another nib for iPad, and just access it when device is iPad.
You all code will remain same, i.e. you don't need to compare iPad like anywhere
Like:
if (cell == nil) {
NSArray *nib;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
nib = [[NSBundle mainBundle] loadNibNamed:#"tvChannelCell-iPad" owner:self options:nil];}
else{
nib = [[NSBundle mainBundle] loadNibNamed:#"tvChannelCell" owner:self options:nil];}
cell = [nib objectAtIndex:0];
}

How to customize a UITableViewCell without any freezing in UITableView

I have customized the table view cell, created nib file and its corresponding .h and .m file. Everything works fine except slowness while scrolling, what could be the problem how can I avoid the freezing?
And
obj = [self.listData objectAtIndex: [indexPath row]];
if (obj != nil) {
static NSString *CellIdentifier;
if (obj->status == status1) {
CellIdentifier = #"Cell_italic";
} else if (obj->status == status2) {
CellIdentifier = #"Cell_cent";
} else {
CellIdentifier = #"Cell";
}
custom_cell *cell = (custom_cell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"custom_cell" owner:self options:nil];
cell = [nib objectAtIndex:0];
char file_path[MAX_PATH]; // Holds file path.
memset(file_path, 0, MAX_PATH);
// Get path
// Set Image
UIImage *cellImage = [UIImage imageWithContentsOfFile:fle_path];
if (cellImage != nil) {
[cell.image_view setImage:cellImage];
}
NSString *combined_name = [NSString stringWithCString:obj->combined_name encoding:NSASCIIStringEncoding];
NSString *email = [NSString stringWithCString:obj->email encoding:NSASCIIStringEncoding];
// Set name
if (obj->status == status1)
{
cell.name_label.text = combined_name;
cell.name_label.font = [UIFont fontWithName:#"Georgia-Italic" size:18];
cell.email_label.text = email;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
. . .
. . .
}
dequeueReusableCellWithIdentifier is always returning nil, Is it right? Without customization I have seen it was not nil many times, now it always returning nil.
image loading each-time that's why Table scroll freezing in UITableView you can implement lazy-loading many way refer bellow links and demos may be its helps you :-
https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
https://github.com/rs/SDWebImage //README Section says,how to use it in your app.
https://github.com/nicklockwood/AsyncImageView/
you can also load image in Background Process using UI thread
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(backgroundQueue,^{
// background process
image = [NSData dataWithContentsOfFile:imageName];
dispatch_async(mainQueue,^{
// always update GUI from the main thread
// uiimageview.image = image.... etc
});
});

Leak when I load custom UITableViewCells from Xib files?

I am getting leak in following code. Leak percentage # the end of the line. Can anyone tell me what is the problem.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
coustomMessage *cell = (coustomMessage *)[tableView dequeueReusableCellWithIdentifier:#"coustomMessage"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"coustomMessage" owner:self options:nil]; (93.1%)
cell = [topLevelObjects objectAtIndex:0];
}
cell.nameLable.text = [self.nameArray objectAtIndex:indexPath.row]; (3.4%)
cell.messageStatusLable.text = [[self.endPointCountArray objectAtIndex:indexPath.row] stringValue]; (3.4%)
return cell;}
are you sure you setted the "identifier" property in your XIB file with the same name you use in your code (with: dequeueReusableCellWithIdentifier:#"coustomMessage")?
Superb! I had exactly the same issue I misspelled the identifier in the XIB and so lots of leaks as the cell we being recreated not re-used. Thanks!

How to Use UISearchBar for Custom Cells in UITableView

I'm populating my tableview from an array. And this array is created by SQLite query.
So in my array, I have objects from my user-defined class.
And I use custom cells in my table. Like object.name in one layer, object.id near this layer.
So far everything's good. But if I try to use UISearchBar, how will I re-populate my table?
This is the code I create my table.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"SpeakersCell";
SpeakersCell *cell = (SpeakersCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"SpeakersCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SpeakersCell class]]) {
cell = (SpeakersCell *) currentObject;
break;
}
}
}
// Set up the cell
ProjectAppDelegate *appDelegate = (ProjectAppDelegate *)[[UIApplication sharedApplication] delegate];
Speaker *speakerObject = (Speaker *)[appDelegate.speakers objectAtIndex:indexPath.row];
cell.lblSpeakerName.text = speaker.speakerName;
cell.lblSpeakerCity.text = speaker.speakerCity;
return cell;
}
When I add a search bar and define searchBar textDidChange event, I successfully get items that contains the key letters. But I can't re-populate my table because I only have searched items' names.
Tutorials I got help from are built on default cells and the datasource of tableview is NSString array. But my array is NSObject array, this is my problem.
I consider getting indexes of searched items but how can I use these values either? Do you have any idea or any related link?
I think you should take a look at Bobgreen's blog, his tutorial helped me quite a lot.
http://www.cocoabob.net/?p=67
Check his delegeate function for UISearchDisplayController (which I guess you might want to use?)
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects];
for (Product *product in listContent)
{
if ([scope isEqualToString:#"All"] || [product.type isEqualToString:scope])
{
NSComparisonResult result = [product.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
[self.filteredListContent addObject:product];
}
}
}
}
He has an array of NSObject's (product) there which he loops thru. Each time a result matches the search string he puts the value in an second array called filteredListContent and he'll show upp the filtered content. Works like a charm for me.