Pull To Refresh on iphone not working as expected - iphone

I have been using this: http://blog.leahculver.com/2010/12/iphone-pull-to-refresh.html to make the pull to refresh function in my app.
But I cant see the text "Pull down to refresh...", "Release to refresh..." and "Loading...".
All I've done is copy the files into my project, link against QuartzCore framework, and changed the .h file of my view controller so it is a subclass of PullRefreshTableViewController. Then I added the refresh method.
Is seems that the initWithStyle method in PullRefreshTableViewController never is executed.
But i should be, in my tableViewcellForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Text";
return cell; }
The initWithStyle method from the PullRefreshTableViewController.m:
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self != nil) {
textPull = [[NSString alloc] initWithString:#"Pull down to refresh..."];
textRelease = [[NSString alloc] initWithString:#"Release to refresh..."];
textLoading = [[NSString alloc] initWithString:#"Loading..."];
NSLog(#"in");
}
NSLog(#"out");
return self; }
The logs are never printed in the console
I really cant see where the problem is ?

Had the same problem.
figured out that not initWithStyle is called instead initWithCoder is called....
so to solve your problem insert following code in your PullRefreshTableViewController.m
and it works like a charm
-(id)initWithCoder:(NSCoder *)aDecoder{
NSLog(#"initWithCoder");
self = [super initWithCoder:aDecoder];
if (self != nil) {
textPull = [[NSString alloc] initWithString:#"Pull down to refresh..."];
textRelease = [[NSString alloc] initWithString:#"Release to refresh..."];
textLoading = [[NSString alloc] initWithString:#"Loading..."];
}
return self;
}
best regards

If you're looking for where the text is defined, it is on Line 43 of the PullRefreshTableViewController.m
Hope this helps (if it does don't forget to vote my answer up)
M.

Try instantiating the PullRefreshTableViewController with:
PullRefreshTableViewController *tableViewController = [[PullRefreshTableViewController alloc] initWithStyle:UITableViewStylePlain];
Instantiating the UITableViewCell using initWithSyle won't have any affect on your UITableViewController subclass.
The alternative is to edit the PullRefreshTableViewController class to override - (id)init method in a similar manner as done with initWithStyle:

Related

Custom UITableViewCell Not Using .xib (Most Likely Because of Flaw in init Method)

I subclassed the UITableViewCell in order to customize it, but I think I'm missing something because: 1) It's not working and 2) There are a couple of things I'm confused on. Along with customizing the look of the .xib file, I also changed the backgroundView, and that part is working fine. The part that I least understand/am most confused about is the init method, so I posted that here. If it turns out that is correct, please tell me so I can post more code that may be the cause.
This is the init method, which I customized. I'm sort of confused around the "style" idea and I think I'm just returning a normal UITableViewCell with a different backgroundView. I mean, there's nothing in there that refers to the .xib or does anything but change the .backgroundView from the self:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier wait: (float) wait fadeOut: (float) fadeOut fadeIn: (float) fadeIn playFor: (float) playFor
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CueLoadingView* lview = [[CueLoadingView alloc] initWithFrame:CGRectMake(0, 0, 320, 53)];
self.backgroundView = lview;
[self setWait:wait]; // in turn edits the lview through the backgrounView pointer
[self setFadeOut:fadeOut];
[self setFadeIn:fadeIn];
[self setPlayFor:playFor];
}
return self;
}
Other than the .xib and several setters and getters, this is the only real part of my code, that relates to retrieving a cell.
Additional Information:
1) This is my .xib, which is linked to the class.
2) This is the code that calls/creates the UITableView (the delegate/view controller):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CueTableCell";
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[CueTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier wait:5.0 fadeOut:1.0 fadeIn:1.0 playFor:10.0];
[cell updateBarAt:15];
}
return cell;
}
The easiest way (available since iOS 5.0) to create a custom table view cell in a nib file is to use registerNib:forCellReuseIdentifier: in the table view controller. The big advantage is that dequeueReusableCellWithIdentifier: then automatically instantiates a cell from the nib file if necessary. You don't need the if (cell == nil) ... part anymore.
In viewDidLoad of the table view controller you add
[self.tableView registerNib:[UINib nibWithNibName:#"CueTableCell" bundle:nil] forCellReuseIdentifier:#"CueTableCell"];
and in cellForRowAtIndexPath you just do
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CueTableCell"];
// setup cell
return cell;
Cells loaded from a nib file are instantiated using initWithCoder, you can override that in your subclass if necessary. For modifications to the UI elements, you should override awakeFromNib (don't forget to call "super").
You have to load the cell from the .xib instead:
if ( cell == nil ) {
cell = [[NSBundle mainBundle] loadNibNamed:#"CellXIBName" owner:nil options:nil][0];
}
// set the cell's properties
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CueTableCell";
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CueTableCell XibName" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [array objectAtIndex:0];
}
return cell;
}

UITableView reloadData crash

I added CustomImageView to the UITableViewCell.
UITableViewCell *cell = nil;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell1"] autorelease];
}
CustomImageView *customIV = [[CustomImageView alloc] init];
[cell.contentView addSubView:customIV];
[customIV release];
But when I try to reload tableview, the error occurs.
error call stack is same as follows.
Output string is as follows.
-[CustomImageView superview]: message sent to deallocated instance 0x1f848f30
CustomImageView *customIV = [[CustomImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[cell.contentView addSubView:customIV];
It's done with me when I've released memory.
So according to me, No need to release, because it'll deallocated memory.
Hopefully, it'll help you.Thanks.
Try to Comment this line[customIV release]; & run , it should not crash while reloading data.
The reason behind this is everytime it tries to create new custom view & releases it, so causes extra load on system & crash occurs.
You only want to add the image once to each cell. Change your code to this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell1"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell1"] autorelease];
CustomImageView *customIV = [[CustomImageView alloc] init];
[cell.contentView addSubView:customIV];
[customIV release];
}
return cell;
}
If this doesn't work then you need to show your complete cellForRowAtIndexPath method. By only showing part of your code you make it difficult to help.
This error occur because each time CustomImageView object created when your cell created.
so, best way is first initialize object of CustomImageView then create your UITableView
such like,
CustomImageView *customIV put it in your .h file and then #synthesize it in .m File
(put this code above UITableView)
self.customIV = [[CustomImageView alloc] init];
Then create UITableView
self.tablView = [[UITableView alloc]init];
.
.
.
.
And in cellForRowAtIndexPath only add [cell.contentView addSubView:self.customIV];

External class object not holding data

I have a class UserData which I imported to this viewcontroller but the data on the cell
is blank.
again userdata is an object of UserData, another class. I did #import "UserData.h" but the table is empty
if I put #"something" in replacement of detailsstring or titlestring, it shows up on the table
- (void)viewDidLoad
{
detailsstring = userdata.details;
titlestring = userdata.title;
tabledata = [[NSMutableArray alloc] initWithObjects:detailsstring, nil];
tablesubtitles = [[NSMutableArray alloc] initWithObjects:titlestring, nil];
[super viewDidLoad];
}
and...
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"homeworkcell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"homeworkcell"];
}
cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [tablesubtitles objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14.0];
You need to share data between view controllers, when you use #import "yourClass" you create an new instanse of that clas with the same name, but will not hold the same content(the new one will be nil). For sharing data between views you can use delegates like this answer, Core data or SQLite can bee used for the same purpose. But delegete is better as i have seen from all the answer&comments out there:)
EDIT As Jack Lawrence too has commented, NSUserDeffaults is not a proper way for sharing data between classes&objects. Just because of its easy-usability I mentioned defaults. I hope this edit will be useful for ones who see this answer later
if you are replacing detailsstring with a string literal and everything works, then detailsstring must be nil in viewDidLoad

Table View not populating

I know this is an oft-asked question/problem. I've looked through a bunch of Q&A for my problem, but I guess I'm a little thick, because I didn't see an answer anywhere.
I have a file with in an array that I would like to use to populate a tableView.
The problem is that it's not being called. Neither is numberOfRowsInSection or numberOfSectionsInTableView. I far as I can see, only viewDidLoad was called.
I have 1 section, the number of elements in my array equals 3 (as opposed to nil).
Relevant code is here...
- (void)viewDidLoad {
[super viewDidLoad];
FileControl *fileArray = [[FileControl alloc] init];
matArray = [fileArray findUniqueItemsInArray:0 :[fileArray setFileToArray]];
[fileArray release];
NSLog(#"%i \n %#", [matArray count], matArray); // matArray is filled.
NSLog(#"ViewDidLoad"); }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(#"CellForRowAtIndexPath");
NSString *text = [matArray objectAtIndex:[indexPath row]];
[[cell textLabel] setText:text];
return cell; }
#interface MaterialTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *materialTableView;
NSArray *matArray;
}
#property (nonatomic, retain) NSArray *matArray;
#end
The other methods are standard.
I guess my problem lies in that I don't completely understand the flow well enough.
Any help would be greatly appreciated. Thanks in advance.
Have you set your UIViewController subclass to be the delegate and dataSource of the UITableView in question? Without doing so, none of the methods you mention will be called.
I suppose you are using a UITableViewController.
If you are using UITableView it is a little bit more complicated (in this case you need to implement UITableViewDelegate, UITableViewDataSource protocols).
[update] This is not your case, you are using UITableViewController.
Add this line to the end of your viewDidLoad method:
[self.tableView reloadData];
Or move this:
FileControl *fileArray = [[FileControl alloc] init];
matArray = [fileArray findUniqueItemsInArray:0 :[fileArray setFileToArray]];
[fileArray release];
to the init method. Your init method should look like this:
- (id)initWithStyle:(UITableViewStyle)style {
if ((self = [super initWithStyle:style])) {
FileControl *fileArray = [[FileControl alloc] init];
matArray = [fileArray findUniqueItemsInArray:0 :[fileArray setFileToArray]];
[fileArray release];
NSLog(#"%i \n %#", [matArray count], matArray); // matArray is filled.
NSLog(#"ViewDidLoad");
}
return self;
}
If you do not see any message in the log, it means that you are not using that method to initialize your object.
Please show all your code in the .m and .h files.
I have a suggestion. Just give a shot for a test. In the - (void)viewDidLoad declare this.
instead of : matArray = [fileArray findUniqueItemsInArray:0 :[fileArray setFileToArray]];
Use this: matArray = [[NSArray alloc] initWithArray:[fileArray findUniqueItemsInArray:0 :[fileArray setFileToArray]]];
Did you use
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.matArray count];
}
make sure you have added your tableview delegate to your .h file as shown below.
#interface YourViewController : UIViewController <UITableViewDelegate> {
}
Also make sure that you have connected your datasource and delegate in interface builder.
Do this by doing:
double click on your .xib file so it opens in interface builder.
left click on your tableview just once so its highlighted blue
right click on your tableview now and a menu should pop up.
drag the datasource & delegate to the files owner box.
make sure to save changes while in interface builder.
This should "connect" all the pieces needed to get it to work.
Happy Coding!!

Memory problem with basic UITableView when scrolling

I have a very simple UITableView that has 3 sections, and 3 rows per section.
#pragma mark -
#pragma mark UITableView delegate methods
- (NSInteger)tableView:(UITableView *)tblView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tblView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tblView
{
if (tblView == self.tableView) {
return 3;
}
else {
return 1;
}
}
Everything shows up fine, but as soon as I scroll my application crashes and my debugger tells me:
***** -[ProfileViewController tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0x5ae61b0**
I'm not exactly sure what I am doing wrong.
EDIT:
This is how I am displaying the ProfileViewController:
ProfileViewController* profileView = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profileView.user_name = username;
profileView.message_source = messageSource;
[self.navigationController pushViewController:profileView animated:YES];
[profileView release];
Looks like your ProfileViewController instance is getting deallocated somehow. Make sure you're not calling its -autorelease after creating it.
Your code seems right. Your bug might be in your model or in the cell configuration. Turn on zombie support for search this kind of error.
something that helped me a similar problem was realizing the following: you may need to retain a table view controller by setting it up as an IBOutlet if it is a subview of another view - i.e. the parent must, in some way, be retaining the child.
Instead of using
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
please use
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
And change your implementation code as follow:
Don't use the below code in "cellForRowAtIndexPath" method. Instead use in "didSelectRowAtIndex" method.
In header(.h) file:
ProfileViewController* profileView;
In implementation (.m) file:
if(profileView==nil)
profileView = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profileView.user_name = username;
profileView.message_source = messageSource;
[self.navigationController pushViewController:profileView animated:YES];