Display multiple uiwebviews in uitablview - ios

I encountered a problem of webview and I thin many people had met that.
In my app, I have an UITableview and each cell of the tableview is self-defined. In each cell a UIWebview is embedded. I need to display each cell's content when I scroll my tableview. (webview's loadsHTML and image_url is from an local array)
Problem is that the UIWebview in each cell loads a remote image url and when user scrolls so fast the table, the webview in the cell can not reac fast enough so the webview may display the repeated image for less than 1 second. (Since I use reusable cell and webview loads from image_url array, so that
image_url = [array_image_url objectAtIndex:[index row]];
For user experience, that is terrible to see the repeated images. I tries to figue it out but still can't. Can anyone help me on this issue?
PS: If possible, I don't want to cache image on disk

I have had a similar problem (I was displaying remote images) and used the UIScrollView delegate methods (UITableView inherits from UIScrollView) to handle when to update my images or not. You can do something similar to load content when the scrolling is stopped:
// UIScrollView Delegate Methods
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
[self loadImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self loadImagesForOnscreenRows];
}
EDIT - Forgot the method that actually loads the rows. This might help :)
Note - Some of this code is specific to my app, you will need to adapt to suit your data and web location of the image. Also - the setImageWithURL method is part of the AFNetworking library. If you haven't checked out AFNetworking, it rocks. If you aren't already using AFN and don't need to, then I also added a class I wrote that uses blocks to async load web images.
- (void)loadImagesForOnscreenRows
{
if ([self.phonebookData count] > 0)
{
NSArray *visiblePaths = [self.myTableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
NSDictionary *selRow = [[self.persons valueForKey:[[[self.persons allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
PBCell *cell = (PBCell *)[self.myTableView cellForRowAtIndexPath:indexPath];
if ([[selRow objectForKey:#"picFileName"] length] > 0) {
[cell.thumbnailImage setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"YourURLHere/%#",[selRow objectForKey:#"picFileName"]]] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
} else {
cell.thumbnailImage.image = [UIImage imageNamed:#"defaultImage.png"];
}
}
}
}
Alternative method instead of AFNetworking:
WebImageOperations.h:
//
// WebImageOperations.h
//
// Created by Larry Wilson on 11/11/11.
// Copyright (c) 2011 Larry Wilson. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface WebImageOperations : NSObject {
}
+ (void)processImageDataWithURLString:(NSString *)urlString andBlock:(void (^)(NSData *imageData))processImage;
#end
WebImageOperations.m:
//
// WebImageOperations.m
//
// Created by Larry Wilson on 11/11/11.
// Copyright (c) 2011 Larry Wilson. All rights reserved.
//
#import "WebImageOperations.h"
#import <QuartzCore/QuartzCore.h>
#implementation WebImageOperations
+ (void)processImageDataWithURLString:(NSString *)urlString andBlock:(void (^)(NSData *imageData))processImage
{
NSURL *url = [NSURL URLWithString:urlString];
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("com.myappname.processimagedataqueue", NULL);
dispatch_async(downloadQueue, ^{
NSData * imageData = [NSData dataWithContentsOfURL:url];
dispatch_async(callerQueue, ^{
processImage(imageData);
});
});
dispatch_release(downloadQueue);
}
#end

Multiple UIWebViews in UITableView is not a good practice.But sometimes we wanna build an app in a short time,UIWebView is a very convenient class for us.
In my case,I set a custom UITableViewCell
CustomTableViewCell.h
#import <UIKit/UIKit.h>
#interface VerticalTableViewCell : UITableViewCell
#property (nonatomic,retain) UIWebView * webView;
-(void)setWebViewContent:(NSString *)htmlContent andIndex:(NSString *)row;
#end
CustomTableViewCell.m
#import "CustomTableViewCell.h"
#interface CustomTableViewCell()
#end
#implementation VerticalTableViewCell
#synthesize webView;
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
if (self) {
self.webView = [[UIWebView alloc]init];
[self.webView setFrame:self.contentView.frame];
[self.webView setUserInteractionEnabled:NO];
[self.contentView addSubview:self.webView];
}
return self;
}
-(void)setWebViewContent:(NSString *)htmlContent andIndex:(NSString *)row
{
[self.webView loadHTMLString:[NSString stringWithFormat:#"<html><head></head><body><div style='width:414px;height:414px;background-image:url(%#);background-size:414px 414px;'></div><p>现在是第%#排</p></body></html>",htmlContent,row] baseURL:nil];
}
- (void) layoutSubviews
{
[super layoutSubviews];
CGRect contentViewFrame = self.contentView.frame;
contentViewFrame.size.width = [[UIScreen mainScreen] bounds].size.width;
contentViewFrame.size.height = 586.0f;
self.contentView.frame = contentViewFrame;
self.webView.frame = contentViewFrame;
}
-(void)dealloc
{
[self.webView loadHTMLString:nil baseURL:nil];
self.webView = nil;
}
#end
CustomTableView.m
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CMainCell = #"CMainCell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CMainCell];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier: CMainCell];
//自定义cell的内容
}
if (self.whiteData!=nil) {
NSString * row = [NSString stringWithFormat:#"%ld",indexPath.row];
[cell setWebViewContent:self.whiteData[indexPath.row] andIndex:row];
//[cell setCustomImage:self.whiteData[indexPath.row]];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell * customCell = (CustomTableViewCell *)cell;
[customCell.webView loadHTMLString:nil baseURL:nil];
}
...
You can see I used the method :
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
In this method,when the cell invisible in tableView,cells will set webViews empty.
In our cases,because of the UITableView Reuse feature,cells won't clean up the contentViews.Therefore users scroll tableView in a very fast way,the cells would be reused and the HTML content is still there.If we clean up the contentView,works well.
But another problem is still here.Because cells should render HTML content when they come into visible area.Rendering speed of UIWebView is not quite fast,so we should write some code for optimizing the rendering process.
Hope this would help you.Cheers.

Related

Play audio From URL when click on a Button inside TableViewCell

My tableView Method is
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
wordsTableViewCell *cell;
if (cell==nil)
{
cell=[tableView dequeueReusableCellWithIdentifier:#"cell"];
}
cell.wordIndexlbl.layer.masksToBounds = true;
cell.wordIndexlbl.layer.cornerRadius = 8;
cell.redWord.text= [self.wordsFromArray objectAtIndex:indexPath.row];
cell.blueWord.text=[self.words objectAtIndex:indexPath.row];
cell.wordIndexlbl.text=[self.wordsID objectAtIndex:indexPath.row];
cell.playCell.tag=indexPath.row;
[cell.playCell addTarget:self action:#selector(playURLCell:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
and then i make a button action and method to call function like this
- (IBAction)playURLCell:(UIButton *)sender
{
UIButton *senderButton=(UIButton *)sender;
NSLog(#"current row = %ld" , (long)senderButton.tag);
[self getWord:_uppercaseString For:_combinedStirng String:wordIndex];
}
-(void)getWord:(NSString*)upperCaseString For:(NSString *)combinedString String:(NSString *)wordIndex
{
BOOL isInternetAvailable = [[NetworkManager sharedInstance] check];
if (isInternetAvailable)
{
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
NSData *data;
NSString *urlStr = [NSString stringWithFormat:#"http://quicklanguages.com/materiales/quicklanguages/audios/%#/%#-%#.mp3",upperCaseString,combinedString,wordIndex];
NSURL *url = [[NSURL alloc] initWithString:urlStr];
[playURLArray addObject:url];
data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
[self playAudio:data];
});
});
}
}
-(void)playAudio :(NSData *)data
{
audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil]; // Now we are assigning it in an instance variable thus ARC will not deallocate it.
audioPlayer.delegate=self;
[audioPlayer play];
}
when I click on button inside from cell , audio not playing and wordIndex goes nill
no error comes what is the problem any one help me
please tell my problem
You have some conceptual errors in code.
I will give you some tips to work better.
a) at:
[cell.playCell addTarget:self action:#selector(playURLCell
You are adding an action to a cell OR to a button?
b) if you have a button, (as You did for other elements, as labels..) add action to it.
c) better to make a custom cell (I see you create a class "wordsTableViewCell", pls use WordsTableViewCell for classes..) AND load it from a separate XIB.
d) do not call dequeueReusableCellWithIdentifier conditionally if nil.. (see code Xcode creates for you for a new TableViewController)
simply use:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WordsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
return cell;
}
e) make some preparation settings and action in "awakeFromNib":
#implementation WordsTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
// set buttons or prepare labels... (or use action from IB..)
}
(labels will be filled up as You already do in cellForRowAtIndexPath)
f) better to use a protocol to let CONTROLLER play (or make the code inside custom code, in the action, but ugly (see below))
g) keep in mind cells are reused so you loose EVERYTHING you have setup when recycled.
h) last but NOT least:
code fails as in:
-(void)playAudio :(NSData *)data
{
audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil]; // Now we are assigning it in an instance variable thus ARC will not deallocate it.
audioPlayer.delegate=self;
[audioPlayer play];
}
As audioPlayer will be released by ARC, so audio stops.
So you must KEEP an AVAudioPlayer instance alive: a viable solution is to put it in Controller.
Let's see the steps:
a) create a protocol, let's say
DidTapToPlayProtocol:
#protocol DidTapToPlayProtocol <NSObject>
#required
-(void)didTapToPlay:(NSInteger)tag;
#end
b)
in custom cell *.h (WordsTableViewCell.h) import protocol and declare a delegate:
#import "DidTapToPlayProtocol.h"
#interface WordsTableViewCell : UITableViewCell
#property (weak, nonatomic) id <DidTapToPlayProtocol>didTapDelegate;
#end
c) in controller, set delegate or cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WordsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
cell.didTapDelegate = self;
return cell;
}
d) in button action call:
-(IBAction)play:(UIButton *)sender {
NSInteger tag ... // get tag..
[self.didTapDelegate didTapToPlay:tag];
}
e) in Table view controller *h allocate a data member:
#interface MyTableViewController : UITableViewController
#property (string, nonatomic) AVAudioPlayer* audioPlayer;
#end
and set it in delegate callback: (now will be retained. Note: we can use a better approach... allocating in in ViewDidLoad.. anyway..)
- (void)didTapToPlay:(NSInteger)tag{
NSData * data;
.....
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
}
(I have written a base code.. if need zip let me know..)

How to filter the multiple selected values from an array and load it to other uitableview from a uibutton

I have 2 UiTableviews in a UiViewController. My exact requirement is to get the selected values from tableview1 and loaded to the tableview2 by tapping the Add Button.
I done Following at the moment
1. loaded JSON Responses to tableview1 (loaded the responses from a filepath at the moment) and printed to a custom nib cell
2. I can get the selected values to a response as follows
Next
3. I want to print that values to *cell2 from the selected values. Please explain the next steps in details.
Here is the UI
Main UI and Description
Here are the codes from table loading to selections.
Object - PSAData.h
#interface PSAData : NSObject
#property (nonatomic, strong) NSString *firstname;
#property (nonatomic, strong) NSString *lastname;
- (void)loadWithDictionary:(NSDictionary *)dict;
#end
Object - PSAData.m
#implementation PSAData
- (void)loadWithDictionary:(NSDictionary *)dict
{
self.firstname=[dict objectForKey:#"firstname"];
self.lastname=[dict objectForKey:#"lastname"];
}
table1 Viewcell - PSATableViewCell.h
#import <UIKit/UIKit.h>
#import "PSAData.h"
#import "NetworkConnectivityClass.h"
#interface PSATableViewCell : UITableViewCell
#property (nonatomic) NetworkConnectivityClass *networkConnectivityClassInstance;
-(void)loadWithData:(PSAData *)psaData;
#end
table1 viewcell - PSATableViewCell.m
#interface PSATableViewCell ()
#property (strong, nonatomic) IBOutlet UILabel *firstnameLbl;
#property (strong, nonatomic) IBOutlet UILabel *lastnameLbl;
#end
#implementation PSATableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
-(void)loadWithData:(PSAData *)psaData
{
[self methodSetupText:psaData];
}
-(void)methodSetupText:(PSAData *)psaData
{
self.firstnameLbl.text=psaData.firstname;
self.lastnameLbl.text=psaData.lastname;
}
#end
Main View Controller - PersonnelViewController
- (void)viewDidLoad {
[super viewDidLoad];
// NSMutableArray *selectedArray=[[NSMutableArray alloc]init];
tableView1.dataSource =self;
tableView1.delegate=self;
tableView2.dataSource=self;
tableView2.delegate=self;
//initializing arrays for get selected values
self.selectedCells=[NSMutableArray array];
self.selectedPSAData=[NSMutableArray array];
//loading web resonse data
self.loadedPSAData=[[NSMutableArray alloc]init];
NetworkConnectivityClass *networkConnectivityClassInstance = [NetworkConnectivityClass new];
__weak PersonnelViewController *weakVersionOfSelf=self;
[networkConnectivityClassInstance methodReturnTableViewMessages:^(NSMutableArray *returnedArrayWithMessages)
{
weakVersionOfSelf.loadedPSAData=returnedArrayWithMessages;
[weakVersionOfSelf.tableView1 reloadData];
}];
//register left side tableview cell (Assigned tableview1)
[self.tableView1 registerNib:[UINib nibWithNibName:#"PSATableViewCell" bundle:nil] forCellReuseIdentifier:#"PSATableViewCell"];
}
//tableview Delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(tableView ==self.tableView1)
{
return 1;
}
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(tableView==self.tableView1)
{
return self.loadedPSAData.count;
}
return self.loadedPSAData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//loading table data into cell tableview1 and tableview2
static NSString *cellIdentifier=#"PSATableViewCell";
PSATableViewCell *cell=[tableView1 dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil) {
cell=[[PSATableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"PSATableViewCell"];
}
//tableview2 implementation
static NSString *cellIdentifier2=#"PSSITableViewCell";
PSSITableViewCell *cell2=[tableView2 dequeueReusableCellWithIdentifier:cellIdentifier2];
if (cell2==nil) {
cell2=[[PSSITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"PSSITableViewCell"];
}
cell.accessoryType = ([self isRowSelectedOnTableView:tableView1 atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
if(tableView == self.tableView1)
{
[cell loadWithData:[self.loadedPSAData objectAtIndex:[indexPath row]]];
}
else if(tableView == self.tableView2)
{
[cell2 loadWithDataS2:[self.loadedPSAData objectAtIndex:[indexPath row]]];
return cell2;
}
return cell;
}
pragma mark - multiple selection
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *psaData =[self.loadedPSAData objectAtIndex:indexPath.row];
PSATableViewCell *cell=[tableView1 cellForRowAtIndexPath:indexPath];
NSString *sampleAH =[self.selectedPSAData description];
if([self isRowSelectedOnTableView:tableView1 atIndexPath:indexPath])
{
[self.selectedCells removeObject:indexPath];
[self.selectedPSAData removeObject:psaData];
cell.accessoryType =UITableViewCellAccessoryNone;
}
else{
[self.selectedCells addObject:indexPath];
[self.selectedPSAData addObject:psaData];
cell.accessoryType =UITableViewCellAccessoryCheckmark;
}
NSLog(#"%#", self.selectedPSAData);
sampleArrayholder.text=[NSString stringWithFormat:#"%#", sampleAH];
}
-(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
return ([self.selectedCells containsObject:indexPath]) ? YES : NO;
}
**Finally NetworkConnectivity class - NetworkConnectivityClass.h **
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "WorksitenameList.h"
#interface NetworkConnectivityClass : NSObject
-(void)methodLogin:(NSString *)stringToLogin withUserName:(NSString *)stringUsername withPassword:(NSString *)stringPassword completion:(void(^)(NSDictionary *))completion;
-(void)methodReturnTableViewMessages:(void (^)(NSMutableArray *))completion;
-(NSURLSessionTaskState)methodCheckIfSessionIsRunning;
-(void)methodCancelNetworkRequest;
#end
**Finally NetworkConnectivity class - NetworkConnectivityClass.m **
-(void)methodReturnTableViewMessages:(void (^)(NSMutableArray *))completion
{
dispatch_queue_t queueForJSON = dispatch_queue_create("queueForJSON", NULL);
dispatch_async(queueForJSON, ^{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"PSAData" ofType:#"json"];
NSError *error = nil;
NSData *rawData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
id JSONData = [NSJSONSerialization JSONObjectWithData:rawData options:NSJSONReadingAllowFragments error:&error];
NSMutableArray *loadedPSAData = [NSMutableArray new];
[loadedPSAData removeAllObjects];
if([JSONData isKindOfClass:[NSDictionary class]])
{
NSArray *loadedArray=[JSONData objectForKey:#"records"];
if([loadedArray isKindOfClass:[NSArray class]])
{
for(NSDictionary *psaDict in loadedArray)
{
PSAData *psaData=[[PSAData alloc]init];
[psaData loadWithDictionary:psaDict];
[loadedPSAData addObject:psaData];
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(loadedPSAData);
NSLog(#"test: %#", loadedPSAData);
});
});
}
I Added All the required codes to have a look at it. Since I am relatively new to iOS Dev. Please Write a codes / instructions step by step clearly to save some time :).
**Please Note : At the moment I loaded the same tableview1 data to tableview2 *cell2 But I want here to load the selected values(Multiple Selection). from tableview1 loadedPSAData Array to load in table view to by tapping an Add Button. Finally sorry for my poor English ;) **
Suppose these 2 are your table outlet.
__weak IBOutlet UITableView * myTable1;
__weak IBOutlet UITableView * myTable2;
You set the Delegate and Data Source like below in your viewDidLoad
myTable1.delegate=self;
myTable1.dataSource=self;
myTable2.delegate=self;
myTable2.dataSource=self;
Now These are 2 Arrays
array1 ==> Which contain All Data
arraySelectedValues ==> Which contain you selected data
So you use this like below
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(self.myTable1 == tableView)
{
return [array1 count];
} else {
return [arraySelectedValues count];
}
}
As I review your Code, Your problem may be in CellForRow. Why to create 2 separate cells, when there is same CellIdentifier. You just need to change the Data.
You should create 2 cells only When Both Tableview are using Diff-Diff tableviewcells. In your case you are using same cell.
Try to modify the code like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier=#"PSATableViewCell";
PSATableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil) {
cell=[[PSATableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifier];
}
if(tableView == myTable1)
{
[cell loadWithData:[array1 objectAtIndex:[indexPath row]]];
}
else if(tableView == myTable2)
{
[cell loadWithData:[arraySelectedValues objectAtIndex:[indexPath row]]];
}
return cell;
}
didSelectRowAtIndexPath should look like :
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(tableView == myTable1)
{
// Your code for highlighting
} else {
// This will be you myTable2 did select click.
}
}
Just When ever you want to refresh the record, you should to Call ReloadData method For respective Tableviews.
Hope you understand how you load the data in 2 Tableviews in Single ViewController.

UICollectionView Appearing Blank

I am trying to use a UICollectionView but I am having a lot of issues. I have a UIViewController with a UICollectionView inside. I have setup all the delegates correctly along with the UILabel in the CVcell. The view appears and is white as defined in the code. The NSLog sends out all the cells and the text that should be there but in the actual UICollectionView it is blank and nothing appears apart from the scroll view. I have tried everything but cannot seem to get this working correctly. The cell is 187 x 187 taking up half the screen size with a label in the middle. I will post the code below.
Thanks
#import "StudentControllerMain.h"
#import "CVcell.h"
#interface StudentControllerMain ()
#property (nonatomic, strong) IBOutlet UICollectionView *collectionView;
#property (nonatomic, strong) NSArray *dataArray;
#end
#implementation StudentControllerMain
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *firstSection = [[NSMutableArray alloc] init];
for (int i=0; i<5; i++) {
[firstSection addObject:[NSString stringWithFormat:#"Cell %d", i]];
}
self.dataArray = [[NSArray alloc] initWithObjects:firstSection, nil];
[self.collectionView registerClass:[CVcell class] forCellWithReuseIdentifier:#"CVcell"];
// Configure layout
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
self.collectionView = nil;
self.dataArray = nil;
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return [self.dataArray count];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSMutableArray *sectionArray = [self.dataArray objectAtIndex:section];
return [sectionArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell identifier
static NSString *cellIdentifier = #"CVcell";
CVcell *cell = (CVcell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSMutableArray *data = [self.dataArray objectAtIndex:indexPath.section];
NSString *cellData = [data objectAtIndex:indexPath.row];
NSLog(cellData);
[cell.title setText:cellData];
[cell.title setTextColor:[UIColor blackColor]];
return cell;
}
#end
remove the register class code;
setting the "identifier" attribute (in attribute inspector) of collection view cell in storyboard;
If you're sure cellForItemAtIndexPath is being called then the issue is the frame of all the views as they are laid out. Run the app and go to that page. Go to Debug -> View debugging -> Capture view hierarchy . This will show you all the views and their sizes. Do you see the table itself? Is it the correct height? Can you see each cell? Can you see their subviews? You can right click each one to print out their dimensions.

Error with scrolling custom table cells in a tableview

Hi I'm a newbie to iOS development I'm facing a problem regarding scrolling of custom cells in a tableview. My table view has around 7 cells but once I scroll the view after running I will be getting only first 5 cells like the below but even tough the rest of the cells are being displayed we can't completely scroll to have a look at those cell.
Here's my viewController.m code
#import "ViewController.h"
#import "MobileTableCell.h"
#interface ViewController ()
{
NSArray *tableData;
NSArray *thumbnails;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tableData = [NSArray arrayWithObjects:#"Iphone 5s",#"Google Nexus 5", #"Samsung Galaxy S4",#"HTC one", #"LG G2", #"Moto X", #"Micromax Turbo", nil];
thumbnails = [NSArray arrayWithObjects:#"iphone5.jpg",#"nexus5.png",#"galaxys4.jpg",#"htcone.jpg",#"lgg2.jpg",#"motox.png",#"micromaxcanvasturbo2.jpg", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"MyMobileTableCell";
MobileTableCell *cell = (MobileTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
//NSLog(#"%#",cell);
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MobileTableCell" owner:self options:Nil];
cell = [nib objectAtIndex:0];
}
// cell.layer.shouldRasterize = YES;
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
#end
Please lemme know where I have gone wrong. Thanks in advance.
You are using a UIViewController to render the UITable because you have: #interface ViewController : UIViewController <UItableViewDelegate , UITableViewDataSource>. Better to directly use the UITableViewController provided #interface ViewController : UITableViewController. If you have a valid reason for using a UIView then you need to set the delegate and dataSource to self:
tableView.delegate = self;
tableView.dataSource = self;
You also need to make sure there isn't anything else that is scrollable on the UIView that makes the table view scroll out of the page like a UIScrollView or something like that. You can use auto layout to help keep your stuff in view.
Last point, your issue might be the result of a UINavigationController covering parts of the table. If you are using a UIView you need to add content margin to the UITable to make sure the navigationController does not hide rows.

Data not loading in Detail View

I'm trying to get my data to load in my detail view. Can any one take a look and see why it isnt showing? It loads fine in my rootviewcontroller, just not the detail view.
DetailViewController.m
#import "DetailViewController.h"
#implementation DetailViewController
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)setIcon:(UIImage *)newIcon
{
[super setIcon:newIcon];
iconView.image = newIcon;
}
- (void)setPublisher:(NSString *)newPublisher
{
[super setPublisher:newPublisher];
publisherLabel.text = newPublisher;
}
- (void)setName:(NSString *)newName
{
[super setName:newName];
nameLabel.text = newName;
}
- (void)dealloc
{
[iconView release];
[publisherLabel release];
[nameLabel release];
[priceLabel release];
[super dealloc];
}
#end
detailviewcontroller.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface DetailViewController : UIViewController {
IBOutlet UIImageView *iconView;
IBOutlet UILabel *publisherLabel;
IBOutlet UILabel *nameLabel;
IBOutlet UILabel *priceLabel;
}
#end
RootViewControllerPoints.m
#import "RootViewControllerPoints.h"
#import "DetailViewController.h"
#define USE_INDIVIDUAL_SUBVIEWS_CELL 1
#define DARK_BACKGROUND [UIColor colorWithRed:151.0/255.0 green:152.0/255.0 blue:155.0/255.0 alpha:1.0]
#define LIGHT_BACKGROUND [UIColor colorWithRed:172.0/255.0 green:173.0/255.0 blue:175.0/255.0 alpha:1.0]
#implementation RootViewController
#synthesize tmpCell, data;
#pragma mark View controller methods
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the table view.
self.tableView.rowHeight = 73.0;
self.tableView.backgroundColor = DARK_BACKGROUND;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// Load the data.
NSString *dataPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
self.data = [NSArray arrayWithContentsOfFile:dataPath];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
return YES;
default:
return NO;
}
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ApplicationCell";
ApplicationCell *cell = (ApplicationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
#if USE_INDIVIDUAL_SUBVIEWS_CELL
[[NSBundle mainBundle] loadNibNamed:#"IndividualSubviewsBasedApplicationCell" owner:self options:nil];
cell = tmpCell;
self.tmpCell = nil;
#endif
}
// Display dark and light background in alternate rows -- see tableView:willDisplayCell:forRowAtIndexPath:.
cell.useDarkBackground = (indexPath.row % 2 == 0);
// Configure the data for the cell.
NSDictionary *dataItem = [data objectAtIndex:indexPath.row];
cell.icon = [UIImage imageNamed:[dataItem objectForKey:#"Icon"]];
cell.publisher = [dataItem objectForKey:#"Publisher"];
cell.name = [dataItem objectForKey:#"Name"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailViewController. = [data objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
#end
This has been bugging me for quite a while, I've looked at numerous examples, tutorials and even asked other iphone devs. Everything source seems to say something different.
First problem is that the setXXX methods in DetailViewController try to make calls to super setXXX but since DetailViewController is a subclass of UIViewController those calls to super will fail because UIViewController doesn't have such methods. Remove the calls to super in the setXXX methods.
Second problem is that the setXXX methods are setting the controls on the DetailViewController directly but the controls won't be accessible until the view is loaded so it won't work if the methods are called before the pushViewController call.
If you change the code in didSelectRowAtIndexPath as follows it should work:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController setName:#"name here"];
[detailViewController setPublisher:#"publisher here"];
[detailViewController setIcon:yourImageVariableHere];
[detailViewController release];
}
Although the above change should work, you might want to consider creating ivars to hold the values in DetailViewController (instead of using the ui controls themselves to hold the data). Then create properties for them using #property and #synthesize. The properties can be set immediately after DetailViewController is created and in the viewDidLoad of the view, you can set the ui controls to the property values. This will give the DetailViewController more control over how its ui is updated, allow you to change the ui without affecting callers, and it doesn't need to be displayed to set its properties.

Resources