SSCollectionView Delegate Problems - iphone

I am having a problem with the SSCollectionView control, a subclass of NSTableView from the SSToolkit. For some reason, all delegates except for - (SSCollectionViewItem *)collectionView:(SSCollectionView *)aCollectionView itemForIndexPath:(NSIndexPath *)indexPath are called. Even though this delegate is #required, removing it will cause no exception either. And before you ask, yes the arrays below all have data in them.
I have checked if the data source/delegate becomes nil at any stage, but it doesn't, so I'm baffled.
Here's how I create the view:
- (void)viewDidLoad
{
NSLog(#"ViewDidLoad");
_titles = [[NSMutableArray alloc] init];
_subtitles = [[NSMutableArray alloc] init];
_thumbnails = [[NSMutableArray alloc] init];
_collectionView = [[SSCollectionView alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.frame];
_collectionView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
[_collectionView setDelegate:self];
[_collectionView setDataSource:self];
[self.view addSubview:_collectionView];
[_collectionView reloadData];
}
This is called fine and the view appears - but with no data.
This method is never called:
- (SSCollectionViewItem *)collectionView:(SSCollectionView *)aCollectionView itemForIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Delegate Called");
static NSString *const itemIdentifier = #"itemIdentifier";
SSCollectionViewItem *item = (SSCollectionViewItem *)[aCollectionView dequeueReusableItemWithIdentifier:itemIdentifier];
if (item == nil)
{
item = [[[SSCollectionViewItem alloc] initWithStyle:SSCollectionViewItemStyleImage reuseIdentifier:itemIdentifier] autorelease];
}
item.textLabel.text = [_titles objectAtIndex:indexPath.row];
item.detailTextLabel.text = [_subtitles objectAtIndex:indexPath.row];
item.imageView.image = [_thumbnails objectAtIndex:indexPath.row];
return item;
}
I don't think this is a bug - did I miss something?

This won't get called if there are no items in your collection view. Make sure the following SSCollectionViewDataSource method is implemented and returns a value greater than zero.
- (NSUInteger)collectionView:(SSCollectionView *)aCollectionView numberOfItemsInSection:(NSUInteger)section
Also, make sure you implement the following SSCollectionViewDelegate method as well so your items will be displayed correctly.
- (CGSize)collectionView:(SSCollectionView *)aCollectionView itemSizeForSection:(NSUInteger)section
I would recommend using SSCollectionViewController if it is the only view in your view controller since it will take care of a lot of the glue code for you.

Try to add your - (CGSize)collectionView:(SSCollectionView *)aCollectionView itemSizeForSection:(NSUInteger)section:before viewDidLoad.. don't know why but it works for me this way

Related

reload tableview after call to WCF service

I am calling a WCF service to display data in a UITableViewController.The code in the .m file is:
- (void)viewDidLoad
{
[super viewDidLoad];
[docTable setDataSource:self];
[docTable setDelegate:self];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
EDViPadDocSyncService *service = [[EDViPadDocSyncService alloc]init];
EDVCategory *cat = [EDVCategory alloc];
cat.categoryId = [catId intValue];
[service getDocsByCatId:self action:#selector(getDocsByCatIdHandler:) category:cat];
[docTable reloadData];
}
- (void) getDocsByCatIdHandler: (id)value
{
if([value isKindOfClass:[NSError class]])
{
NSLog(#"%#", value);
return;
}
if([value isKindOfClass:[SoapFault class]])
{
NSLog(#"%#", value);
return;
}
NSMutableArray* result = (NSMutableArray*)value;
NSMutableArray *documentList = [[NSMutableArray alloc] init];
self.myDocList = [[NSMutableArray array] init];
for (int i = 0; i < [result count]; i++)
{
EDVDocument *docObj = [[EDVDocument alloc]init];
docObj = [result objectAtIndex:i];
[documentList addObject:[docObj docName]];
}
self.myDocList = documentList;
[docTable reloadData];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int cnt = [self.myDocList count];
NSLog(#"ABC=%#",cnt);
return [self.myDocList count];
//return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DocumentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DocumentCell"];
if (cell == nil)
{
cell = [[[DocumentCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"DocumentCell"] autorelease];
}
NSLog(#"cell text=%#",[self.myDocList objectAtIndex:indexPath.row]);
cell.lblDocName.text = [self.myDocList objectAtIndex:indexPath.row];
return cell;
}
I am using storyboard.I have hooked the "docTable",set the datasource and the delegate for "docTable".The problem is,the service is called after the call to "numberOfRowsInSection".So,'return [self.myDocList count]' is 0.I have put [docTable reloadData] in viewWillAppear as well as in the service handler,that is,"getDocsByCatIdHandler".But it isn't getting reloaded,as expected.Is there anything else I can try? EDIT:- This a Master-Detail application.I have used the same code for loading data in the "MasterViewController" UITableViewController and it works.When the user selects a cell in this table,I need to populate data in the second tableview by calling the WCF service.The second tableview isn't displaying data.
Everything looks good which leads me to believe you are not getting the results from the webservice you are expecting.
One small thing first thats not your problem. If result is in fact an array and there is an object in it, you shouldnt need to alloc a new EDVDocument.
EDVDocument *docObj = [result objectAtIndex:i];
Can you log the (id)value parameter to see what we're working with?
NSLog(#"%#", value);
If value is not an array, the cast wont complain, it will just work by not working. However, if it is an array you may be finding trouble with assigning your property (granted I dont know how its declared) to a local array. You can use the following function to create a new array with the elements of your temporary array;
self.myDocList = [[NSArray alloc] initWithArray:documentList];
[docTable reloadData];
I hope this helps.
I was facing the same issue when i have a async webService call. I was using a private Library to call webservice so my control goes to the library and after the response comes a method in Appdelegate is set as handler. So what you need to do is before calling the Webservice save the state of tableview in a shared variable and after you have received response set it back to tableView and then call the reload method. Something like below:
SharedView.tblView = self.tableView;
[webservice Call];
After Response:
self.tableView = SharedView.tblView;
[self.tableView reloadData];
Hope This Helps.

does reload tabledata affect cellForRowAtIndexPath

I am currently trying to set up my tableview, when its first loaded I call my connection class which in turn calls my parser class then inside my parser class I call a method in my ViewController, which is the original view that is being set up. This method is passed an array which will be used latter.
The method passes the array to an array variable in this ViewController, in this method I then call
[self.tableView reloadData];
and what I am wanting that to do is reload cellForRowAtIndexPath so that it will go through my logic (if statements) and check if ([returnedArray count] != 0){ then do its thing.. but the thread never makes it back to this delegate method, which in turn never makes it back to the if statment.
MORE INFO :)
So first of all, when the the ViewController loads
tableView:cellForRowAtIndexPath: is called and sets up my UITableView that all looks perfect, it then calls my NSURLConnection method which connects to my server downloads all of the data and then passes that over to my parser class. From there my parser dose its thing, and everything is fine.
This is what the code looks like in my tableView:cellForRowAtIndexPath:, method
//..
if (indexPath.row == 0){
if ([FilterArray count] == 0){
[cellActivityIndicator startAnimating];
//-- Start NSURLConnection
EngineRequests *engineRequests = [[EngineRequests alloc] init];
[engineRequests initalizePacketVariables];
}
if ([FilterArray count] != 0){
[cellActivityIndicator stopAnimating];
cell.accessoryView = nil; //hides activity indicator
cell.userInteractionEnabled = YES;
cell.backgroundColor = [UIColor whiteColor];
UILabel *label1;
label1 = (UILabel *)[cell viewWithTag:1];
label1.textColor = [UIColor darkGrayColor];
UILabel *label2;
label2 = (UILabel *)[cell viewWithTag:2];
label2.textColor = [UIColor darkGrayColor];
//...etc
Inside my parser class's parserDidEndDocument method I am passing the NSArray back to the MainView.
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#",#"ISCHECKED",#"T"];
NSArray *filteredArray = [parsedDataArrayOfDictionaries filteredArrayUsingPredicate:predicate];
//call method in VieController1 to pass array over
SearchViewController *searchViewController = [[SearchViewController alloc] init];
[SearchViewController initFilterArray:filteredArray];
}
So then I head back over to my VC1 and the method that I have declared in the .h and then obviously in the .m file
and this is all of the code that I have in it.
#pragma - Reciver methods
-(void)initFilterArray:(NSArray*)array
{
//initalise array variable for use in latter views
FilterArray = array;
//reload to make cell white
[self.tableView reloadData];
// NSLog(#"%#", FilterArray);
}
While debugging the code the thread makes it to this method and runs everything.. if I uncomment that NSLog, it displays my filitered array and everything. However for some reason the reloadData dose not seem to call tableView:cellForRowAtIndexPath:.. I know this because I have debugged it with breakpoints etc.
So... hopefully this added information will help you help me :)
[self.tableView reloadData];
it will call the delegate methods.
if it isn't, you can check if self.tableView is linked to the tableView you want to reload.

Three20 TTTableViewController and searchViewController

I am trying to implement adding recipients to TTMessageController based on the example from TTCatalog.
Everything works fine until I enter search controller - I can search and get results, but nothing happens when I select items. I tried to set delegates, but none works.
- (void)loadView {
[super loadView];
TTTableViewController* searchController = [[TTTableViewController alloc] init];
searchController.dataSource = [[FriendsDataSource alloc] initWithApi:self.appDelegate.api];
searchController.variableHeightRows=YES;
self.searchViewController = searchController;
self.tableView.tableHeaderView = _searchController.searchBar;
}
In TTCatalog, items in search have an URL directing to google - that's not very helpful ;)
OK, I've found the answer :)
One line was missing from the code above. I had a feeling I should set the delegate, but didn't know where:
- (void)loadView {
[super loadView];
TTTableViewController* searchController = [[TTTableViewController alloc] init];
searchController.dataSource = [[FriendsDataSource alloc] initWithApi:self.appDelegate.api];
self.searchViewController = searchController;
_searchController.searchResultsTableView.delegate=self;
self.tableView.tableHeaderView = _searchController.searchBar;
}
Then it as enough to add this to allow variable heights:
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
id<TTTableViewDataSource> dataSource = (id<TTTableViewDataSource>)tableView.dataSource;
id object = [dataSource tableView:tableView objectForRowAtIndexPath:indexPath];
Class cls = [dataSource tableView:tableView cellClassForObject:object];
return [cls tableView:tableView rowHeightForObject:object];
}
And this to handle selection:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TTTableImageItemCell *cell = (TTTableImageItemCell *) [tableView cellForRowAtIndexPath:indexPath];
TTTableImageItem *object = [cell object];
[_delegate MessageAddRecipient:self didSelectObject:object];
}

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!!

Pull To Refresh on iphone not working as expected

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: