adding property to UITableView subclass - iphone

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;
}

Related

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
});
});

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.

UiTextField in a UITableViewCell get empty when scrolling

I'm using a UITableView grouped to display my application preferences.
I get the cell with this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger section = [indexPath section];
NSInteger row = [indexPath row];
NSInteger identifier = row + ((section + 1) * 10);
NSString *CellIdentifier = [NSString stringWithFormat:#"CustomCellIdentifier-%d",identifier];
LoginTableViewCell *cell = (LoginTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LoginTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
cell.field.tag = identifier;
if (section == 0) {
switch (row) {
case 0:{
NSString *user = [[NSUserDefaults standardUserDefaults] valueForKey:#"username"];
cell.field.text = user;
cell.label.text = #"User";
break;
}
case 1:{
NSString *bundleName = [[NSBundle mainBundle] bundleIdentifier];
NSError *error = nil;
NSString *user = [[NSUserDefaults standardUserDefaults] objectForKey:#"username"];
NSString *pwd = [SFHFKeychainUtils getPasswordForUsername:user andServiceName:bundleName error:&error];
cell.field.text = pwd;
cell.field.secureTextEntry = YES;
cell.label.text = #"Password";
break;
}
case 2:{
NSString *numero = [[NSUserDefaults standardUserDefaults] valueForKey:#"numero"];
cell.field.text = numero;
cell.field.keyboardType = UIKeyboardTypePhonePad;
cell.label.text = #"Number";
break;
}
default:
break;
}
if (cell.field.text > 0) {
cell.field.enabled = NO;
cell.field.borderStyle = UITextBorderStyleNone;
}
} else {
switch (row) {
case 0:{
cell.field.text = [NSString stringWithFormat:#"+%#", [[NSUserDefaults standardUserDefaults] valueForKey:#"prefix"]];
cell.field.keyboardType = UIKeyboardTypePhonePad;
cell.label.text = #"Prefix";
break;
}
case 1:{
cell.field.text = [[NSUserDefaults standardUserDefaults] valueForKey:#"sender"];
cell.field.keyboardType = UIKeyboardTypeNamePhonePad;
cell.label.text = #"Sender";
break;
}
default:
break;
}
}
}
return cell;
}
The problem is that, when a row scrolls outside the window, the textfield get empty.
How can I prevent this?
I thought caching was the right solution, but even with the reusable identifier, I still have the same problem.
The approach you're using, that is loading the table cell from a nib file, requires - in order to have correct reusable cells support - to assign in the nib "Identifier" field the same string identifier you use in the code. That is, if your cell identifier used for cache deque is "MyCellId" then your UITableCellView "Identifier" field in the nib file must contain this same "MyCellId" identifier.
But with the approach you are following this is not possible, as the cell ID is dynamically generated and then you cannot of course dynamically assign the cell identifier to the nib-loaded cell.
In theory you must create a specific nib file for each of the MyCellId-%d identifiers you generate.
As I assume you have only one table cell defined, get rid of the dynamic identifier generation and use a static name and then assign this name to the "Identifier" field in the cell nib file .

XIB backed View with Subclassing

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

Error with UITableViewCell

I am getting an error of:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x26e9d68'
I have a FriendViewCell class which has a UIImageView and two other labels as an IBOutlet. Setting the property and synthesize it (basic stuffs). I have connected the outlets to the corresponding label and imageview and change the class type to FriendViewCell, set the identity to that as well
The partial code I have is the following:
FriendViewCell *cell = (FriendViewCell *)[tableView dequeueReusableCellWithIdentifier:#"FriendViewCell"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"FriendViewCell"
owner:nil options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (FriendViewCell *) currentObject;
break;
}
}
}
Rather than grabbing the array and searching for your cell, can you simply add an IBOutlet to your tableviewcontroller?
#property (nonatomic, assign) IBOutlet UITableViewCell *tvCell;
then in code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FriendViewCell"];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"FriendViewCell" owner:self options:nil];
cell = tvCell;
}
You would need to link the IBOutlet to the cell in Interface Builder.
Have you tried to locate what is the instance 0x26e9d68 using the Allocations tracing?