I want to connect an my app to the database and display it in a Label.
I could connect my app to the database and display it in the UITableView.
This is what I have so far:
Viewontroller.h
#import <UIKit/UIKit.h>
#interface CartHistoryViewController : UITableViewController
{
NSMutableArray *arrayDataFromServer;
}
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/CartGet.php? choice=history"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
strURL = #"http://localhost:8888/CartGet.php?choice=historydate";
NSArray *arrayImagesPaths = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
// store the result in arrayDataFromServer
arrayDataFromServer = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
NSEnumerator *enumForPahts = [arrayImagesPaths objectEnumerator];
id objName, objPath;
while ( objName = [enumForNames nextObject]) {
objPath = [enumForPahts nextObject];
[arrayDataFromServer addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", objPath, #"path", nil]];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"name"];
[cell.textLabel setFont:[UIFont systemFontOfSize:20]];
cell.detailTextLabel.text = [[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"path"];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"path"]]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
cell.imageView.image = img;
return cell;
}
I want to be able to display it in a Label and in an ImageView instead of a cell. Please help.
Go to your Interface Builder choose your table view and make it Grouped TableView
add below code before your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrayDataFromServer count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
// set header height of gropued tableview
-(CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section
{
return 120;//change this value if it is too big
}
//set header section labels
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
NSString * subject=[[arrayDataFromServer objectAtIndex:section] objectForKey:#"name"];//this line may give you error because of section easy to correct
UILabel *subjectLabel = [[UILabel alloc] initWithFrame:CGRectMake(45, 30, 100, 100)];
subjectLabel.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
subjectLabel.font = [UIFont fontWithName:#"Arial" size:25];
subjectLabel.text = subject;
subjectLabel.backgroundColor = [UIColor clearColor];
[subjectLabel sizeToFit];
// if you want to add image view create an imageview programatically here
// NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[[arrayDataFromServer objectAtIndex:section] objectForKey:#"path"]]];
//NSData *data = [NSData dataWithContentsOfURL:url];
//UIImage *img = [UIImage imageWithData:data];
// UIImageView *brickAnim = [[UIImageView alloc] initWithImage:img];
// Create header view and add label as a subview choose coordinates wisely
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 120, 100, G00)];
[view addSubview:subjectLabel];
//[view addSubview:brickAnim];
return view;
}
Related
I am working on chat application. Actually i have 3 arrays. First array stores user name and second array stores chat message and third array stores images. I am picking image from photo gallery.
When user sends any message to the chat wall I display message in bubble.
So I'm writing some conditions like the below:
if arr2 value is not null then displaying chat message
if arr3 value is not null displaying image in chat bubble
if arr2 value is null then i want to hide lbldesc and show only imv gallery image
if arr3 value is null then hide imv gallery image and enable lblDesc
But i got exception like this:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** NSAllocateMemoryPages(4294967295) failed'`
Here is my code:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.selectionStyle=UITableViewCellSelectionStyleNone;
if (itemsDataArr.count>0) {
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(35, 3, 250, 80)];
imgView.image = [UIImage imageNamed:#"speech-bubble-2-hi.png"];
imgView.layer.borderColor = [UIColor clearColor].CGColor;
imgView.tag = 5;
[cell.contentView addSubview:imgView];
NSArray *arr1=[[NSArray alloc]init];
arr1=[itemsUserNameArr objectAtIndex:indexPath.row];
NSString *strval=[arr1 objectAtIndex:0];
lblTitle=[[UILabel alloc]initWithFrame:CGRectMake(50, 5, 150, 20)];
lblTitle.highlightedTextColor=[UIColor whiteColor];
[cell.contentView addSubview:lblTitle];
[lblTitle setFont:[UIFont boldSystemFontOfSize:14]];
lblTitle.text=strval;
[imgView addSubview:lblTitle];
NSArray *arr2=[[NSArray alloc]init];
arr2=[itemsDataArr objectAtIndex:indexPath.row];
NSArray *arr3=[[NSArray alloc]init];
arr3=[itemImgArray objectAtIndex:indexPath.row];
if(![arr2 isEqual:#""])
{
NSString *strmsg=[arr2 objectAtIndex:0];
lblDesc=[[UILabel alloc]initWithFrame:CGRectMake(50, 22, 300, 20)];
lblDesc.highlightedTextColor=[UIColor whiteColor];
lblDesc.font=[UIFont systemFontOfSize:12.0];
[cell.contentView addSubview:lblDesc];
[lblDesc setHidden:NO];
lblDesc.text=strmsg;
[imgView addSubview:lblDesc];
// imv.hidden=YES;
// [imv setHidden:true];
}
arr3=[itemImgArray objectAtIndex:indexPath.row];
if(![arr3 isEqual:nil])
{
NSString *strImg=[arr3 objectAtIndex:0];
NSData *data = [[NSData alloc] initWithData:[NSData dataFromBase64String:strImg]];
//Now data is decoded. You can convert them to UIImage
imv = [[UIImageView alloc]initWithFrame:CGRectMake(93,12, 50, 50)];
imv.image=[UIImage imageWithData:data];
[imgView addSubview:imv];
[lblDesc setHidden:YES];
// lblDesc.hidden=YES;
}
}
return cell;
}
I've used PTSMessagingCell from here:
I've used messages array for texts/images. This is a ruf sample that may help you.
#import "ViewController.h"
#import "PTSMessagingCell.h"
#interface ViewController ()
{
NSMutableArray *messages;
UITextView *sendMsg;
UITableView *chatTable;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
messages = [[NSMutableArray alloc] initWithObjects:#"Hello",[UIImage imageNamed:#"download.jpeg"],#"Check This Out", nil];
chatTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height-100)];
chatTable.delegate = self;
chatTable.dataSource = self;
chatTable.separatorColor = [UIColor clearColor];
[self.view addSubview:chatTable];
chatTable.backgroundColor = [UIColor clearColor];
sendMsg = [[UITextView alloc]initWithFrame:CGRectMake(0, chatTable.frame.size.height, self.view.frame.size.width-100, 100)];
sendMsg.textColor = [UIColor blackColor];
sendMsg.delegate = self;
sendMsg.backgroundColor = [UIColor whiteColor];
sendMsg.layer.cornerRadius = 3.0f;
[self.view addSubview:sendMsg];
UIButton *sendMsgbtn = [[UIButton alloc]initWithFrame:CGRectMake(sendMsg.frame.size.width, chatTable.frame.size.height, 100, 100)];
[sendMsgbtn setTitle:#"SEND" forState:UIControlStateNormal];
sendMsgbtn.backgroundColor = [UIColor redColor];
[sendMsgbtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sendMsgbtn addTarget:self action:#selector(sendClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sendMsgbtn];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[chatTable addGestureRecognizer:tapGestureRecognizer];
}
-(void)sendClicked{
[sendMsg resignFirstResponder];
[chatTable reloadData];
}
#pragma mark - TableView Delegate and DataSource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/*This method sets up the table-view.*/
static NSString* cellIdentifier = #"messagingCell";
PTSMessagingCell * cell = (PTSMessagingCell*) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[PTSMessagingCell alloc] initMessagingCellWithReuseIdentifier:cellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[messages objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]]) {
return [(UIImage *)[messages objectAtIndex:indexPath.row] size].height;
}
else{
const char *jsonString = [[NSString stringWithFormat:#"%#",[messages objectAtIndex:indexPath.row]] UTF8String];
NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)];
NSString *goodMsg = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding];
CGSize messageSize = [PTSMessagingCell messageSize:goodMsg];
NSLog(#"%f",messageSize.height + 2*[PTSMessagingCell textMarginVertical] + 40.0f);
return messageSize.height + 2*[PTSMessagingCell textMarginVertical] + 40.0f;
}
}
-(void)configureCell:(id)cell atIndexPath:(NSIndexPath *)indexPath {
if (messages.count>0) {
PTSMessagingCell* ccell = (PTSMessagingCell*)cell;
if ([[messages objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]]) {
ccell.sent = YES;
ccell.avatarImageView.image = [UIImage imageNamed:[messages objectAtIndex:indexPath.row]];
ccell.messageLabel.text = #"";
}
else{
ccell.sent = YES;
const char *jsonString = [[NSString stringWithFormat:#"%#",[messages objectAtIndex:indexPath.row]] UTF8String];
NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)];
NSString *goodMsg = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding];
ccell.messageLabel.text = [messages objectAtIndex:indexPath.row];
}
ccell.timeLabel.text = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterFullStyle];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[ccell addGestureRecognizer:tapGestureRecognizer];
}
}
-(void)tapReceived:(UITapGestureRecognizer *)tapGestureRecognizer
{
// do something, like dismiss your view controller, picker, etc., etc.
[sendMsg resignFirstResponder];
}
Hope this helps.
Create a custom cell and load images in background thread will give better UI performance
I've tried using ASyncImageView for this purpose, but I'm a bit confused as to how I'd implement it for my specific case. I currently have a MatchCenterViewController that contains a table inside of it. It's loading the images for the cells synchronously, which is causing a lot of lag when scrolling through the table. How can I modify the way I'm loading the remote images so that it's done asynchronously? My code is below:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#import "MatchCenterCell.h"
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#property (nonatomic, assign) BOOL matchCenterDone;
#property (nonatomic, assign) BOOL hasPressedShowMoreButton;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_matchCenterDone = NO;
_hasPressedShowMoreButton = NO;
// Set up MatchCenter table
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,70,320,self.view.frame.size.height-100);
self.edgesForExtendedLayout = UIRectEdgeAll;
self.matchCenter.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, CGRectGetHeight(self.tabBarController.tabBar.frame), 0.0f);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
self.expandedSection = -1;
_matchCenterArray = [[NSArray alloc] init];
// Refresh button
UIImageView *refreshImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"refresh.png"]];
refreshImageView.frame = CGRectMake(280, 30, 30, 30);
refreshImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(refreshPressed:)];
[refreshImageView addGestureRecognizer:tapGesture];
[self.view addSubview:refreshImageView];
// Preparing for MC and indicating loading
self.matchCenterArray = [[NSArray alloc] init];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
[self.view addSubview: activityIndicator];
[activityIndicator startAnimating];
_matchCenterDone = NO;
// Disable ability to scroll until table is MatchCenter table is done loading
self.matchCenter.scrollEnabled = NO;
[PFCloud callFunctionInBackground:#"MatchCenter3"
withParameters:#{}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[activityIndicator stopAnimating];
[_matchCenter reloadData];
_matchCenterDone = YES;
self.matchCenter.scrollEnabled = YES;
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 21.0f;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 40;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
//code snipped out for conciseness
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
//Header code snipped out for conciseness
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *currentSectionDictionary = _matchCenterArray[section];
NSArray *top3ArrayForSection = currentSectionDictionary[#"Top 3"];
return (top3ArrayForSection.count-1 < 1) ? 1 : top3ArrayForSection.count-1;
}
// Cell layout
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"MatchCenterCell";
MatchCenterCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[MatchCenterCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//[cell.contentView addSubview:cell.priceLabel];
[cell.contentView addSubview:cell.conditionLabel];
// No cell seperators = clean design
tableView.separatorColor = [UIColor clearColor];
NSDictionary *currentSectionDictionary = _matchCenterArray[indexPath.section];
NSArray *top3ArrayForSection = currentSectionDictionary[#"Top 3"];
if (top3ArrayForSection.count-1 < 1) {
// title of the item
cell.textLabel.text = #"No items found, but we'll keep a lookout for you!";
cell.textLabel.font = [UIFont systemFontOfSize:12];
}
else {
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Title"];
cell.textLabel.font = [UIFont systemFontOfSize:14];
// price + condition of the item
NSString *price = [NSString stringWithFormat:#"$%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Price"]];
NSString *condition = [NSString stringWithFormat:#"%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Item Condition"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", price, condition];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 2.5;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == self.expandedSection || indexPath.row <= 3) {
return 65;
}
return 0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_matchCenterDone == YES) {
self.itemURL = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Item URL"];
[self performSegueWithIdentifier:#"WebViewSegue" sender:self];
}
}
#end
#implementation MoreButton
#end
// Use background thread to avoid the laggy tableView
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Download or get images here
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"url"]];
UIImage *cellImage = [[UIImage alloc] initWithData:imageData];
// Use main thread to update the view. View changes are always handled through main thread
dispatch_async(dispatch_get_main_queue(), ^{
// Refresh image view here
[cell.imageView setImage:cellImage];
[cell.imageView.layer setMasksToBounds:YES];
[cell.imageView.layer setCornerRadius:2.5f];
[cell setNeedsLayout];
});
});
The most common solution to this is AFNetworking's AFImageView. It handles this situation perfectly. It should take you no time at all to implement, so give it a go.
Guy Kogus' answer works great. He's right, I got into all kinds of issues like he mentions in the comment above, doing similar things like the first answer.
Still, here's an example on how to use AFNetworking's UIImageView category. Assuming the code below is in a Cell (or something inheriting from a UIView).
First import the class:
#import "UIImageView+AFNetworking.h"
Then add this code in your UITableViewCell:
NSString *url = #"http://www.domain.www/some_image.jpg";
[self.productImage setImageWithURL:[NSURL URLWithString:url]
placeholderImage:[UIImage imageNamed:#"placeholderImg.png"]];
[self setNeedsLayout];
Not 100% sure if setNeedsLayout is necessary in this case. Feel free to correct this.
My Parse cloud code sends back JSON to my iOS app with the following structure:
What I want to do is iterate through this and create a new section in the UITableView for every object in this matchCenterArray.
In this instance, there are three objects in the array, each contains a Top 3 NSDictionary whose value is an array of 3 items, each of which is yet another array of properties. As you can see, I want it set up so that each section has 3 cells, one for each of the top 3 items of that respective matchCenterArray object. I then want it to pull the properties of each item and display it in each cell as the texLabel, detailTextLabel, and thumbnail.
I've tried using a for loop as a solution, but this displays the same item in all cells of the array. This is probably because I'm only looping through matchCenterArray objects, but not additionally looping through items in those objects, as can be seen here:
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:i] objectForKey:#"Top 3"] objectAtIndex:0]objectForKey:#"Title"];
What I was thinking of doing is nesting a for loop within this one, in place of objectAtIndex:0, but sending a message to a for loop doesn't work.
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
_matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:#"MatchCenterTest"
withParameters:#{
#"test": #"Hi",
}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[_matchCenter reloadData];
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 21.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
headerView.backgroundColor = [UIColor lightGrayColor];
// _searchTerm = [[self.matchCenterArray firstObject] objectForKey:#"Search Term"];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
// headerLabel.text = [NSString stringWithFormat:#"%#", searchTerm];
// headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
// headerLabel.textColor = [UIColor whiteColor];
headerLabel.backgroundColor = [UIColor lightGrayColor];
[headerView addSubview:headerLabel];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = section + 1000;
button.frame = CGRectMake(300, 2, 17, 17);
[button setImage:[UIImage imageNamed:#"xbutton.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:button];
return headerView;
}
- (IBAction)deleteButtonPressed:(UIButton *)sender {
NSLog(#"Search Term: '%#'", _searchTerm);
[PFCloud callFunctionInBackground:#"deleteFromMatchCenter"
withParameters:#{
#"searchTerm": _searchTerm,
}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
for (int i = 0; i<[_matchCenterArray count]; i++) {
// populate dictionary with results
//NSDictionary *matchCenterDictionary= [_matchCenterArray objectAtIndex:indexPath.row];
// title of the item
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:i] objectForKey:#"Top 3"] objectAtIndex:0]objectForKey:#"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#", [[[[_matchCenterArray objectAtIndex:i] objectForKey:#"Top 3"] objectAtIndex:0]objectForKey:#"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[[_matchCenterArray objectAtIndex:i] objectForKey:#"Top 3"] objectAtIndex:0] objectForKey:#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
//imageView.frame = CGRectMake(45.0,10.0,10,10);
}
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - 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.
}
*/
#end
Forget about the loops, the delegate method already run on a loop where the iteration number is equal to the datasource count.
numberOfSectionsInTableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
numberOfRowsInSection
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section{
return _matchCenterArray[section][#"Top 3"].count;
}
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// Initialize cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Price"];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
}
Don't harcode your array count, if your json changes, your code will need to change.
In the future you should look into loading the images asynchronously using a library like SDWebImage in order to avoid lags.
cellForRowAtIndexPath: is called once per numberOfRowsInSection:
You need to add numberOfSections as well:
it should look like this:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// the following will set the cell attributes for cells in each section
// to customize per section, use indexPath.section to get which section you are at
// title of the item
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:indexPath.row objectForKey:#"Top 3"] objectAtIndex:0]objectForKey:#"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#", [[[[_matchCenterArray objectAtIndex:indexPath.row] objectForKey:#"Top 3"] objectAtIndex:0]objectForKey:#"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[[_matchCenterArray objectAtIndex:indexPath.row] objectForKey:#"Top 3"] objectAtIndex:0] objectForKey:#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
}
Please refer to apple's tableView guide
I'm parsing a JSON string into a custom table view cell.
How can I resize the label's height to fit the content text and also resize the cell to fit it's content.
The code:
#import "DEMOSecondViewController.h"
#import "DEMONavigationController.h"
#import "PostsObject.h"
#import "RNBlurModalView.h"
#import "AFNetworking.h"
#interface DEMOSecondViewController ()
#end
#implementation DEMOSecondViewController
#synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"iCelebri.com";
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Menu"
style:UIBarButtonItemStylePlain
target:(DEMONavigationController *)self.navigationController
action:#selector(showMenu)];
self.tableView.separatorColor = [UIColor clearColor];
// Setting Up Activity Indicator View
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.activityIndicatorView.hidesWhenStopped = YES;
self.activityIndicatorView.center = self.view.center;
[self.view addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
self.tableView.separatorColor = [UIColor clearColor];
// Initializing Data Source
self.movies = [[NSArray alloc] init];
[self makeConnection];
}
-(void)makeConnection {
_url = [[NSURL alloc] initWithString:#"my-site.com/json.php?name=Name"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:_url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.movies = JSON;
[self.activityIndicatorView stopAnimating];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
}
// Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.movies && self.movies.count) {
return self.movies.count;
} else {
return 0;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 124;
}
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setBackgroundColor:[UIColor clearColor]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"PostsObject";
PostsObject *cell = (PostsObject *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PostsObject" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = imageView;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
cell.title.text = [movie objectForKey:#"message"];
cell.published.text = [movie objectForKey:#"published"];
return cell;
}
#end
So I want the cell to resize to the size of the title label plus text label
"message": [movie objectForKey:#"message"];
How can I do this?
This Is a full code for resizing the cell's height according to the text length for each indexPath:
The .h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
IBOutlet UITableView *_tableView;
UIActivityIndicatorView *_activityIndicatorView;
NSArray *_movies;
CGFloat cellTextWidth;
CGFloat cellHeightExceptText;
}
#property (nonatomic, retain) UIFont *fontForCellText;
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, retain) UIActivityIndicatorView *activityIndicatorView;
#property (nonatomic, retain) NSArray *movies;
#end
The .m file:
#import "ViewController.h"
#import "AFNetworking.h"
#import "ParseFeedCell.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies;
#synthesize fontForCellText;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ParseFeedCell" owner:self options:nil];
ParseFeedCell *cell = [nib objectAtIndex:0];
fontForCellText = cell.title.font;
cellTextWidth = cell.title.frame.size.width;
cellHeightExceptText = cell.frame.size.height - cell.title.frame.size.height;
[self.navigationController setNavigationBarHidden:YES];
self.tableView.separatorColor = [UIColor clearColor];
// Setting Up Activity Indicator View
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.activityIndicatorView.hidesWhenStopped = YES;
self.activityIndicatorView.center = self.view.center;
[self.view addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
self.tableView.separatorColor = [UIColor clearColor];
// Initializing Data Source
//self.movies = [[NSArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"your-website.com/json_file?name=Name"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.movies = [[NSArray alloc] initWithArray:JSON];
[self.activityIndicatorView stopAnimating];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
}
// Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.movies && self.movies.count) {
return self.movies.count;
} else {
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"ParseFeedCell";
ParseFeedCell *cell = (ParseFeedCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ParseFeedCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
NSString *strText = [movie objectForKey:#"message"];
CGRect rect = cell.title.frame;
rect.size.height = [self getHeightForText:strText];
cell.title.frame = rect;
cell.title.text = strText;
cell.arrow.center = CGPointMake(cell.arrow.frame.origin.x, rect.origin.y + rect.size.height/2);
cell.published.text = [movie objectForKey:#"published"];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
NSString *strText = [movie objectForKey:#"message"];
CGFloat cellHeight = cellHeightExceptText + [self getHeightForText:strText];
return cellHeight;
}
- (CGFloat)getHeightForText:(NSString *)strText
{
CGSize constraintSize = CGSizeMake(cellTextWidth, MAXFLOAT);
CGSize labelSize = [strText sizeWithFont:fontForCellText constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
NSLog(#"labelSize.height = %f",labelSize.height);
return labelSize.height;
}
Make sure that the Autolayout for your custom cell "ParseFeedCell" is off (Not Checked):
Also change the number of Lines of the text UILabel to 999999 so it's not limited to lines.
I am sure that with a bit of research you can find a way to know how many lines the text is and assign the lines to the UILabel programatically.
Use this to a dynamic sized cell:
Start by defining the following:
#define FONT_SIZE 13.0f
#define CELL_CONTENT_WIDTH 290.0f
#define CELL_CONTENT_MARGIN 19.0f
Implement the following helper method;
-(CGSize)frameForText:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size {
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
NSDictionary * attributes = #{NSFontAttributeName:font,
NSParagraphStyleAttributeName:paragraphStyle
};
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
// This contains both height and width, but we really care about height.
return textRect.size;
}
In your UITableViewDelegate Height method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
NSString *text = [movie objectForKey:#"message"];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [self frameForText:text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint];
CGFloat height = MAX(size.height, 14.0f);
return height + CELL_CONTENT_MARGIN;
}
Set the frame and text in your UITableViews cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"PostsObject";
PostsObject *cell = (PostsObject *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PostsObject" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = imageView;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
NSString *text = [movie objectForKey:#"message"];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [self frameForText:text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint];
cell.txtLabel.text = text;
cell.txtLabel.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 14.0f));
cell.published.text = [movie objectForKey:#"published"];
return cell;
}
If you want the cell to resize based on the content of the JSON you have to change the following method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 124;
}
You're setting the height of each cell to 124px. What you should do instead it's to:
Get the size of the string rendered with the
specified constraints.
Reset the frame of the label that contains the string
Return the right size for the cell in
tableView:heightForRowAtIndexPath:
Hope it helps!
Cheers
How I can add prefix tel:65 to my phone number, that I fetched from address book in array.
If I do this in viewdidload it's getting null
NSURL *phoneUrl = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phoneNumbers]];
NSLog(#"Some Text %#", phoneUrl);
NSLog(#"Phone Numbers %#", phoneNumbers);
Here phoneNumbers is array with numbers per each contact
Udate:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"BG.jpg"]]];
[detailTableView setBackgroundColor:[UIColor clearColor]];
detailTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
ShadowTable *Shadow = [[ShadowTable alloc] init];
[Shadow ForTableView:detailTableView ForView:self.view HeaderAlpha:0.3 FooterAlpha:0.6];
for(int i = 0 ; i <[phoneNumbers count]; i++)
{
NSURL *phoneUrl = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", [phoneNumbers objectAtIndex:i]]];
NSLog(#"Phone with URL %#", phoneUrl);
NSLog(#"Phone Numbers %#", phoneNumbers);
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [phoneTypes 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];
}
UILabel *typeLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 100, 40)];
typeLabel.text = [phoneTypes objectAtIndex:indexPath.row];
[typeLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:typeLabel];
UILabel *numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(130, 10, 170, 40)];
numberLabel.text = [phoneNumbers objectAtIndex:indexPath.row];
[numberLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:numberLabel];
if (indexPath.row %2 == 0) {
cell.contentView.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
} else {
cell.contentView.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
}
//cell.textLabel.text = [phoneNumbers objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You are using an array not a string. So you need to access all elements of array to add as suffix.
Use this :
for(int i = 0 ; i <[phoneNumbers count]; i++)
{
NSString *str = [#"tel:" stringByAppendingFormat:#"%#",[phoneNumbers objectAtIndex:i]];
str = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *phoneUrl = [NSURL URLWithString:str];
NSLog(#"Some Text %#", phoneUrl);
}
EDIT : Url was null because there were spaces in "2013-05-31 14:58:24.759 GTCallBack[8225:c07]" so encode it to remove spaces.
Hope it helps you.