I'm trying to display data in Today Widget extension in UIViewController subclass. The number of items (rows) is alway 3 but the tableView:cellForRowAtIndexPath: is called only once.
I've double-checked everything but cannot find a bug.
Any suggestions?
Thanks!
#import "TodayViewController.h"
#import "FLWAccount.h"
#import "FLWAccountTableViewCell.h"
#import "FLWAuthManager.h"
#import <NotificationCenter/NotificationCenter.h>
#interface TodayViewController () <NCWidgetProviding, UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, readwrite, weak) IBOutlet UITableView
*tableView;
#end
#implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 79.0f;
self.tableView.rowHeight = 79.0f;
[self updatePreferredContentSize];
[self.tableView reloadData];}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
[[FLWAuthManager sharedManager] updateAllAccountsWithCompletion:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self updatePreferredContentSize];
[self.tableView reloadData];
completionHandler(NCUpdateResultNewData);
});
}]; }
#pragma mark - UITableViewDataSource, UITableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = [FLWAuthManager sharedManager].accounts.count;
return count; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FLWAccountTableViewCell *cell = (FLWAccountTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"FLWAccountTableViewCell" forIndexPath:indexPath];
cell.account = [FLWAuthManager sharedManager].accounts[indexPath.row];
return cell; }
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 79.0f; }
- (void)updatePreferredContentSize {
NSInteger count = [FLWAuthManager sharedManager].accounts.count;
self.preferredContentSize = CGSizeMake(self.preferredContentSize.width, 79.0f * count); }
#end
If you are using storyboard, check if the table view content is set to "Dynamic Prototypes" (and NOT "Static cells")
Related
I have a UITableView inside a UITableViewCell and I need to figure out how to set the sub table view datasource and delegate. At the moment this is what I have:
MainTableViewController.h
#import <UIKit/UIKit.h>
#interface MainTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
#end
MainTableViewController.m
#import "MainTableViewController.h"
#import "TableViewCell.h"
#interface MainTableViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation MainTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"tableViewCell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.cellLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.row];
return cell;
}
#end
TableViewCell.h
#import <UIKit/UIKit.h>
#interface TableViewCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UILabel *cellLabel;
#property (weak, nonatomic) IBOutlet UITableView *subTableView;
#end
TableViewCell.m
#import "TableViewCell.h"
#implementation TableViewCell
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.subTableView.delegate = self;
self.subTableView.dataSource = self;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"subTabeViewCell"];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"subTabeViewCell"];
cell.textLabel.text = #"test";
return cell;
}
#end
Because I can't ctrl + drag from my sub table view to the TableViewCell class, I'm trying to set the delegate and datasource programmatically within the initialisation, but it's not working and I'm just getting straight up confused.
I know I can set the datasource and delegate to connect to the first class and then within each of the delegate functions check to see which tableView I'm dealing with, but the with the nature of what I'm trying to do it won't really work, I've tried.
So all help is welcome
So I figured it out, well i figured out a way of doing it. Within the cellForRowAtIndexPath in the MainTableViewController.m, I simply added:
[cell.subTableView setDelegate:cell];
[cell.subTableView setDatasource:cell];
And all is working away
I have a view controller with a static cell named 'Make' I have two controllers one called "AddCarTableViewController" and "MakeTableViewController" when you click on the static cell named 'Make' it presents the make table view controller where you can select the make, then pops the view controller and am trying to store the selected value in the detailTextLabel of the static cell. here is my code for all the controllers.
The problem I'm having is once I select the make everything happens as it should I even log the selected item and it saves it after popping the view controller, but I can't figure out how to implement selected item into the detailTextLabel. Any help will be much appreciated!
"MakeTableViewController.h"
#import <UIKit/UIKit.h>
#import "AddCarTableViewController.h"
#protocol CarMakeDelegate <NSObject>
- (void)updateCarMake:(NSString *)updateMake;
#end
#interface MakeTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *carMakes;
#property (nonatomic, weak) id <CarMakeDelegate> delegate;
#end
MakeTableViewController.m
#import "MakeTableViewController.h"
#interface MakeTableViewController ()
#end
#implementation MakeTableViewController {
NSIndexPath *oldIndexPath;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc] initWithObjects:#"Acura", #"Aston Martin", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.carMakes count];
}
- (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];
}
cell.textLabel.text = [self.carMakes objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
oldIndexPath = indexPath;
NSString *addMake = self.carMakes[indexPath.row];
[self.delegate updateCarMake:addMake];
NSLog(#"%#", addMake );
[[self navigationController] popViewControllerAnimated:YES];
}
#end
AddCarTableViewController.h
#import <UIKit/UIKit.h>
#import "MakeTableViewController.h"
#interface AddCarTableViewController : UITableViewController
#property (strong, nonatomic) NSString *makeName;
#property (weak, nonatomic) IBOutlet UITableViewCell *makeCell;
#end
AddCarTableViewController.m
#import "AddCarTableViewController.h"
#interface AddCarTableViewController ()
#end
#implementation AddCarTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 4;
}
-(void)updateCarMake:(NSString *)updateMake {
self.makeCell.detailTextLabel.text = updateMake;
}
#end
You don't need to use delegate in this case. Just update the underlying data model. and call
[tableview reloadData];
When the makeViewController is popped.
In the AddCarVC's cellForRowAtIndex, add another line to check if current indexPath corresponds to Make cell and if it does update the detailLabel text.
I currently have a MatchCenterViewController that I want to programmatically turn into a UITableViewController. I've attempted to do so below based on tutorials I've found, but it doesn't seem to be appearing.
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#end
#implementation MatchCenterViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"newFriendCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//etc.
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
#end
As a minimum, you need to implement the following methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
And you need to set the delegate and datasource, typically in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
}
Also, you need an IBOutlet to the table view if the table view was created in storyboard, or a property for the table view, if the table view was created in code.
So I have a UITableView as a subview of another view in interface builder, and it is not rendering. I've already checked that the number of sections method is returning 1, and that the number of rows in section method is returning a number > 0.
This is my code -
- (void)viewDidLoad{
//[super viewDidLoad];
_trendingImageView.image = [UIImage imageNamed:#"trending.png"];
[self.scrollView setScrollEnabled:YES];
[self.scrollView setClipsToBounds:YES];
self.scrollView.delegate = self;
UINib *nib = [UINib nibWithNibName:#"RecommendationCell"
bundle:nil];
[self.recommendationsTableView registerNib:nib forCellReuseIdentifier: reco
recommendationCellIdentifier];
self.recommendationsTableView.scrollEnabled = YES;
}
-(void)executeRecSearch{
#try{
[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:[NSString stringWithFormat:someUrl]] callback:^(NSDictionary *returnjson){
if(returnjson != nil){
self.recommendations = returnjson[#"Node"][#"Recommendations"][#"Components"];
NSLog(#"COUNT: %d", [self.recommendations count]);
[self performSelectorOnMainThread:#selector(renderRecommendations) withObject:nil waitUntilDone:YES];
}
}];
} #catch (NSException* e) {
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sections{
return [self.recommendations count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
-(void)renderRecommendations{
self.recommendationsTableView.hidden = FALSE;
[self.recommendationsTableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"CELL INDEX PATH CALLED: %#", self.recommendations);
RecommendationCell *cell = [self.recommendationsTableView dequeueReusableCellWithIdentifier:recommendationCellIdentifier];
if(self.recommendations != nil){
NSDictionary* recommendationData = self.recommendations[indexPath.row];
}
return cell;
}
I also checked that the delegate and dataSource were linked to the File's Owner in the connections manager.
Why is the draw method not being called?
This is my .h file
#interface BasicCardViewController : UIViewController<RateViewDelegate, UIScrollViewDelegate, UITableViewDelegate,UITableViewDataSource>
#property(atomic)NSInteger rating;
#property(copy,nonatomic)NSString *userPageLink;
#property(copy,nonatomic)NSString *nodePage;
#property(strong, nonatomic)NSString* description;
#property(strong,nonatomic)NSString* pageScore;
#property(strong,nonatomic)NSString* pageTitle;
#property(strong,nonatomic)NSString* phoneNumber;
#property(strong,nonatomic)NSString* address;
#property(weak,nonatomic)NSArray* recommendations;
#property(atomic)NSInteger* numberOfRecommendations;
#property (strong, nonatomic) IBOutlet TooviaRateView *rateView;
#property(strong,nonatomic)IBOutlet UIImageView *restaurantImageView;
#property(strong,nonatomic)UIImage* restaurantImage;
#property(strong,nonatomic)IBOutlet UITextView* descriptionView;
#property(strong,nonatomic)IBOutlet UIImageView* trendingImageView;
#property(strong,nonatomic)IBOutlet UILabel* pageScoreLabel;
#property(strong,nonatomic)IBOutlet UILabel* pageTitleLabel;
#property(strong,nonatomic)IBOutlet UIScrollView* scrollView;
#property(strong,nonatomic)IBOutlet UILabel* phoneNumberLabel;
#property(strong,nonatomic)IBOutlet UILabel* addressLabel;
#property(strong,nonatomic)IBOutlet UITableView* recommendationsTableView;
- (IBAction)logOut:(id)sender;
- (IBAction)writeRecommendation:(id)sender;
- (IBAction)call:(id)sender;
-(IBAction)map:(id)sender;
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sections;
#end
This is what I get when I print out data source and delegate-
2013-12-17 17:58:41.473 ReviewApp[17451:a0b] DATA SOURCE : *nil description*
2013-12-17 17:58:41.473 ReviewApp[17451:a0b] Data Delegate : *nil description*
You have to create the cell in
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
dequeueReusableCellWithIdentifier
will return nil if no cell is available to dequeue.
Modify it to something similar to this:
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"CELL INDEX PATH CALLED: %#", self.recommendations);
RecommendationCell *cell = [self.recommendationsTableView dequeueReusableCellWithIdentifier:recommendationCellIdentifier];
if(cell==nil){
cell = [[UITableViewCell alloc]init];
}
if(self.recommendations != nil){
NSDictionary* recommendationData = self.recommendations[indexPath.row];
}
return cell;
}
I had the same problem, none of the provided examples worked, so I rolled out a a simple delay function.
class func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
}}
func renderCategories () {
Utils.delay(1) {
self.tableView.reloadData()
}
}
After a ton of stuff - this worked -
I checked use autolayout for the table view(it had been unchecked before, I guess because this view exists inside of a scroll view, and I had unchecked autolayout for that). It then drew - I have no idea why.
I am trying to implement a UITableView. My issue is that tableview cells, in order to be selected in simulator, require the user to press and hold that cell. I don't understand why this is happening. I would like cell's to be selected with a simple tap. Here is my code. There isn't much.
The header file:
#import "BasisViewController.h"
#define kDISCUSSIONS 5
#interface MyDiscussionsViewController : BasisViewController <UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *myDiscussionsTable;
#end
The implementation file:
#import "MyDiscussionsViewController.h"
#interface MyDiscussionsViewController ()
#end
#implementation MyDiscussionsViewController
#synthesize myDiscussionsTable;
- (void)viewDidLoad
{
[super viewDidLoad];
// Annoyingly, iOS 7 makes it so the seperators of table views are offset slightly. Get rid of this property.
if ([myDiscussionsTable respondsToSelector:#selector(setSeparatorInset:)]) {
[myDiscussionsTable setSeparatorInset:UIEdgeInsetsZero];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return kDISCUSSIONS;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TheDiscussions";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
[cell.textLabel setText:#"This Discussion"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"User selected discussion at index: %d",indexPath.row);
}
#end