I'm trying to make an item feed with a UITableView and some JSON objects,
but when I try filling an instance of my custom cell with the JSON data, the UILabels won't change their text.
The JSON has been tested and works. It goes through the loop and creates the right amount of rows. But the text isn't changing to the text from the JSON file.
Here's my code:
feed.m
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *FeedURL = [NSURL URLWithString:#"http://www.personeelsapp.jordivanderhek.com/company/bijcasper/nieuws.json"];
NSData *jsonData = [NSData dataWithContentsOfURL:FeedURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", dataDictionary);
self.posts = [NSMutableArray array];
PostsArray = [dataDictionary objectForKey:#"feed"];
for (NSDictionary *bpdDictionary in PostsArray) {
// make new post object
FeedPosts *posts = [FeedPosts InitPost];
NSLog(#"feed check %#" ,[bpdDictionary objectForKey:#"name"]);
posts.postTitle = [bpdDictionary objectForKey:#"name"];
posts.postProfilepic = [bpdDictionary objectForKey:#"profilePic"];
posts.postDatum = [bpdDictionary objectForKey:#"timeStamp"];
posts.postMessage = [bpdDictionary objectForKey:#"status"];
posts.postImage = [bpdDictionary objectForKey:#"image"];
[self.posts addObject:posts];
}
}
[…]
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
return [self.posts count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Cellindentifier = #"PostCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Cellindentifier forIndexPath:indexPath];
// Configure the cell...
FeedPosts *posts = [self.posts objectAtIndex:indexPath.row];
cell.postTitle.text = #"test title";
cell.postDatum.text = posts.postDatum.text;
cell.postMessage.text = posts.postMessage.text;
return cell;
}
}
FeedPosts.h
#property (strong, nonatomic) IBOutlet UILabel *postTitle;
#property (strong, nonatomic) IBOutlet UILabel *postMessage;
#property (strong, nonatomic) IBOutlet UIImageView *postImage;
#property (strong, nonatomic) IBOutlet UIImageView *postProfilepic;
#property (strong, nonatomic) IBOutlet UILabel *postDatum;
// designated init
+ (id) InitPost;
FeedPosts.m
+ (id) InitPost {
// init new feed item
return [[self alloc]init];
}
have been getting the following error:
-[__NSCFString text]: unrecognized selector sent to instance
What am I doing wrong?
You have declared several UILabels in FeedPosts.
#property (strong, nonatomic) IBOutlet UILabel *postTitle;
In the following code, you assign NSString (text) to the label object:
FeedPosts *posts = [FeedPosts InitPost];
NSLog(#"feed check %#" ,[bpdDictionary objectForKey:#"name"]);
posts.postTitle = [bpdDictionary objectForKey:#"name"];
Instead, you should set the text for those labels:
posts.postTitle.text = [bpdDictionary objectForKey:#"name"];
Same goes for postMessage and postDatum.
Related
When i parsing json with tableview everything good when have json items but if not load json items and when i clicked back button gives me this error.
erminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
I think json don't load when i clicked fastly back button and gives this error my table view codes under.
#interface MasterViewController ()
#property (nonatomic, assign) NSInteger currentPage;
#property (nonatomic, assign) NSInteger totalPages;
#property (nonatomic, assign) NSInteger totalItems;
#property (nonatomic, assign) NSInteger maxPages;
#property (nonatomic, strong) NSMutableArray *activePhotos;
#property (strong, nonatomic) NSMutableArray *staticDataSource;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
self.activePhotos = [[NSMutableArray alloc] init];
self.searchResults = [[NSMutableArray alloc] init];
self.staticDataSource = [[NSMutableArray alloc] init];
}
#pragma mark - Table View
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.activePhotos.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if (indexPath.row == [self.activePhotos count]) {
cell = [self.tableView dequeueReusableCellWithIdentifier:#"LoadingCell" forIndexPath:indexPath];
UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:100];
[activityIndicator startAnimating];
} else {
NSDictionary *photoItem = self.activePhotos[indexPath.row];
cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [photoItem objectForKey:#"name"];
if (![[photoItem objectForKey:#"description"] isEqual:[NSNull null]]) {
cell.detailTextLabel.text = [photoItem objectForKey:#"description"];
}
}
return cell;
}
- (void)loadPhotos:(NSInteger)page
{
NSString *userismim =[[NSUserDefaults standardUserDefaults] stringForKey:#"userisim"];
NSArray* words = [userismim componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString* nospacestring = [words componentsJoinedByString:#""];
NSLog(#"%#",nospacestring);
NSString *apiURL = [NSString stringWithFormat:#"http://bla.com/server/table.php?user=%#",nospacestring];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:apiURL]
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (!error) {
NSError *jsonError = nil;
NSMutableDictionary *jsonObject = (NSMutableDictionary *)[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
NSLog(#"%#",jsonObject);
[self.staticDataSource addObjectsFromArray:[jsonObject objectForKey:#"photos"]];
self.currentPage = [[jsonObject objectForKey:#"current_page"] integerValue];
self.totalPages = [[jsonObject objectForKey:#"total_pages"] integerValue];
self.totalItems = [[jsonObject objectForKey:#"total_items"] integerValue];
self.activePhotos = self.staticDataSource;
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}] resume];
}
Thanks for everything . i need your help.
You are showing activity indicator which will keep rotating till json loads.
If you are pressing back button before json loads, what happens is app tries to allocate empty reference to array which is not possible, so it throws an error.
To avoid this, you can stop userInteraction once request goes, and enable only after getting success or failure response.
To disable interaction, add
[[UIApplication sharedApplicaton] beginIgnoringInteractionEvents]
after
NSURLSession *session = [NSURLSession sharedSession];
And to enable again, add :
[[UIApplication sharedApplicaton] endIgnoringInteractionEvents]
before
if (!error) {
This will solve your issue I hope.
I need to help with my code. I am getting longitudes and latitudes as a response from a web service. I need to convert them to a location name and show it in respective table view cell label.
Following are the response, code and screen shot of my view where I show my converted city, country name, and correct my code where i am doing mistake.
#import <UIKit/UIKit.h>
#import "JobTableViewCell.h"
#import "SlideNavigationController.h"
#import <CoreLocation/CoreLocation.h>
#interface JobPostedViewController : UIViewController <SlideNavigationControllerDelegate, UITableViewDataSource, CLLocationManagerDelegate>
#property (strong, nonatomic) NSArray* job_id;
#property (strong, nonatomic) NSArray* assigned_user_id;
#property (strong, nonatomic) NSArray* job_title;
#property (strong, nonatomic) NSArray* job_description;
#property (strong, nonatomic) NSArray* job_priority;
#property (strong, nonatomic) NSString* job_longitude;
#property (strong, nonatomic) NSArray* date;
#property (strong, nonatomic) NSString* job_latitude;
#property (strong, nonatomic) NSArray* job_completed;
#property (strong, nonatomic) NSArray* job_start_date;
#property (strong, nonatomic) NSArray* bids;
#property (nonatomic, strong) CLGeocoder *myGeocoder;
- (IBAction)onClickJobButton:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *sideNavigation;
#property (weak, nonatomic) IBOutlet UITableView *jobPostedTableView;
#end
`
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.jobPostedTableView.dataSource = self;
//Slide Navigation
[self.sideNavigation addTarget:[SlideNavigationController sharedInstance] action:#selector(toggleLeftMenu) forControlEvents:UIControlEventTouchUpInside];
WebManager *manager = [WebManager sharedInstance];
[manager getJobPostedWithCompletionBlock:^(id response){
NSDictionary *dictionary = (NSDictionary *)response;
// Read data from JSON
NSDictionary *responseObject = [dictionary objectForKey:#"response"];
NSLog(#"The Array%#",responseObject);
self.bids = [responseObject objectForKey:#"bids"];
self.job_description = [responseObject objectForKey:#"job_description"];
self.job_id = [responseObject objectForKey:#"job_id"];
self.job_completed = [responseObject objectForKey:#"job_completed"];
self.job_latitude = [responseObject objectForKey:#"job_latitude"];
self.job_longitude = [responseObject objectForKey:#"job_longitude"];
self.job_priority = [responseObject objectForKey:#"job_priority"];
self.job_start_date = [responseObject objectForKey:#"job_start_date"];
self.job_title = [responseObject objectForKey:#"job_title"];
[self.jobPostedTableView reloadData];
}];
CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:[self.job_latitude floatValue] longitude:[self.job_longitude floatValue]]; //insert your coordinates
[ceo reverseGeocodeLocation:loc
completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"placemark %#",placemark);
//String to hold address
[[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
NSLog(#"addressDictionary %#", placemark.addressDictionary);
NSArray *ar = [placemark.addressDictionary objectForKey:#"locality"];
NSLog(#"placemark %#",ar); // Extract the city name
NSLog(#"placemark %#",placemark.country); // Give Country Name
}
];
}
#pragma mark - SlideNavigationController Methods
- (BOOL)slideNavigationControllerShouldDisplayLeftMenu
{
return YES;
}
#pragma mark - TableView Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.job_title count];
}
- (NSInteger) numberOfSectionsInTableview:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"JobTableViewCell";
JobTableViewCell *cell = (JobTableViewCell *)[self.jobPostedTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[JobTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// Comparing array string to display an urgent image
if ([[self.job_priority objectAtIndex:indexPath.row]
isEqualToString:#"urgent"]) {
cell.urgentLabel.hidden = NO;
} else {
cell.urgentLabel.hidden = YES;
}
// Condition whether job completed is open or closed
if ([[self.job_completed objectAtIndex:indexPath.row]
isEqualToString:#"1"]) {
cell.jobStatus.text = #"Open";
[cell.jobStatus setTextColor:[UIColor colorWithRed:(84/255.f) green:(56/255.f) blue:(255/255.f) alpha:1.0f]];
cell.flagImage.image = [UIImage imageNamed:#"jobPosted_opened.PNG"];
} else {
cell.jobStatus.text = #"Closed";
[cell.jobStatus setTextColor:[UIColor colorWithRed:(179/255.f) green:(179/255.f) blue:(180/255.f) alpha:1.0f]];
cell.flagImage.image = [UIImage imageNamed:#"jobPosted_closed.PNG"];
}
cell.jobTitle.text = [self.job_title objectAtIndex:indexPath.row];
cell.jobContent.text = [self.job_description objectAtIndex:indexPath.row];
cell.bidsLabel.text = [[self.bids objectAtIndex:indexPath.row ]stringValue];
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Here's the solution:
Change NSString to NSArray of these properties:
#property (strong, nonatomic) NSString* job_longitude;
#property (strong, nonatomic) NSString* job_latitude;
Add a new property to hold the geocode results:
#property (strong, nonatomic) NSMutableDictionary* reversedGeocodes;
Set reversedGeocodes in viewDidLoad: method:
self.reversedGeocodes = [NSMutableDictionary dictionary];
Add this method to get the reversed geoCode (and save it for the future):
- (void)locationNameWithLat:(float)lat
lng:(float)lng
completionHandler:(void (^)(NSString *locationName, NSError *error))completion
{
if (!lat || !lng)
completion(#"Unknown location", nil);
if (!completion || !lat || !lng)
return;
NSString *latStr = #(lat).description;
NSString *lngStr = #(lng).description;
// For each pair of lat and lng creating a unique key and saving the result
// so we don't have to process the same pair multiple times.
// Example:
// lat = 23.039567; lng = 72.566004;
// key = #"23.03956772.566004"; value would be whatever CoreLocation returns
NSString *key = [latStr stringByAppendingString:lngStr];
if (key.length) {
if ([self.reversedGeocodes[key] length]) {
completion (self.reversedGeocodes[key], nil);
} else {
self.reversedGeocodes[key] = #"Loading...";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
completion(#"Unknown location", error);
} else {
CLPlacemark *placemark = placemarks.firstObject;
NSString *locationName = placemark.country; // Default = country
if (placemark.locality.length) // add city if available
locationName = [NSString stringWithFormat:#"%#, %#", placemark.locality, placemark.country];
self.reversedGeocodes[key] = locationName.length ? locationName : #"Unknown location";
completion(self.reversedGeocodes[key], nil);
}
}
];
}
} else {
completion(#"Unknown location", nil);
}
}
Call the above method from cellForRowAtIndexPat: method before your return the cell:
float lat = self.job_latitude[indexPath.row];
float lng = self.job_longitude[indexPath.row];
[self locationNameWithLat:lat
lng:lng
completionHandler:^(NSString *locationName, NSError *error) {
cell.locationName.text = locationName;
}];
return cell;
P.S. Let me know if I missed anything or misspelled because I typed some of the code on here...
When I scroll down in my tableView some contents of cells disappear (labels and imageViews).
My code:
-(void)viewWillAppear:(BOOL)animated{
[comentarios removeAllObjects];
NSString *lookup=[NSString stringWithFormat:#"http://my.url"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:lookup]];
[request setHTTPMethod:#"GET"];
NSError *error = nil; NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#",jsonDict);
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come=[[Comentario alloc] init];
come.nick=[[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment=[[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar=[[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
}
[self reloadInputViews];
[self.comentariosTableView reloadData];
}
and
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if( cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
}
// Display recipe in the table cell
UIImageView *avatar = (UIImageView *)[cell viewWithTag:100];
avatar.image = [UIImage imageNamed:[[comentarios objectAtIndex:indexPath.row] avatar]];
UILabel *nick = (UILabel *)[cell viewWithTag:101];
nick.text =[[comentarios objectAtIndex:indexPath.row] nick];
UILabel *comment = (UILabel *)[cell viewWithTag:102];
comment.text = [[comentarios objectAtIndex:indexPath.row] comment];
UIButton *sinvoto = (UIButton *)[cell viewWithTag:103];
UIButton *ticket = (UIButton *)[cell viewWithTag:104];
return cell;
}
I can't see the mistake, please help me.
Thank you in advance
EDIT Nª1
just changed this
ViewController.m
#import "ViewController.h"
#import "SimpleTableCell.h"
#interface ViewController (){
NSMutableArray *comentarios;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.comenatrioTableView.delegate=self;
self.comenatrioTableView.dataSource=self;
self.automaticallyAdjustsScrollViewInsets = NO;
UIImage *plus=[[UIImage imageNamed:#"megafono.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc] initWithImage:plus style:UIBarButtonItemStylePlain target:self action:#selector(comenta:)];
self.navigationController.navigationBar.barTintColor=[UIColor colorWithRed:204.0/255.0 green:0.0/255.0 blue:00.0/255.0 alpha:1.0f];
comentarios=[[NSMutableArray alloc] init];
[self reloadInputViews];
}
-(void)viewWillAppear:(BOOL)animated{
[comentarios removeAllObjects];
NSString *lookup=[NSString stringWithFormat:#"http://myURL"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:lookup]];
[request setHTTPMethod:#"GET"];
NSError *error = nil; NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#",jsonDict);
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come=[[Comentario alloc] init];
come.nick=[[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment=[[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar=[[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
}
[self reloadInputViews];
}
-(void)viewDidAppear:(BOOL)animated{
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [comentarios count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 110;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
Comentario *comentario=[[Comentario alloc] init];
comentario =[comentarios objectAtIndex:indexPath.row];
cell.avatar.image=[UIImage imageNamed:[comentario avatar]];
cell.nick.text=[comentario nick];
cell.comment.text =[comentario comment];
return cell;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
-(void)comenta:(id)sender{
[self performSegueWithIdentifier:#"goComment" sender:self];
}
#end
and ViewController.h
#import <UIKit/UIKit.h>
#import "Comentario.h"
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *comenatrioTableView;
#end
Edit Nª3
The proble is when I scroll down, the information of cells become nil but comentarios Array have the information.
Edit Nª4
here is the project https://github.com/QuimeraKoke/BANG-
I have a couple of other suggestions that will improve your code.
You have to call super in viewDidAppear and viewWillAppear methods:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
}
Instead of using:
Comentario *comentario = [[Comentario alloc] init];
comentario = [comentarios objectAtIndex:indexPath.row];
with:
Comentario *comentario = [comentarios objectAtIndex:indexPath.row];
Finally, you should check your dataSource:
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come = [[Comentario alloc] init];
come.nick = [[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment = [[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar = [[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
NSLog(#"nick = %#, comment = %#, avatar = %#", come.nick, come.comment, come.avatar);
}
EDIT:
Instead of using:
#interface Comentario : NSObject
#property (weak,nonatomic) NSString *nick;
#property (weak,nonatomic) NSString *comment;
#property (weak,nonatomic) NSString *avatar;
#end
you should use:
#interface Comentario : NSObject
#property (copy,nonatomic) NSString *nick;
#property (copy,nonatomic) NSString *comment;
#property (copy,nonatomic) NSString *avatar;
#en
Your problem has been resolved.
Copy
copy is required when the object is mutable. Use this if you need the
value of the object as it is at this moment, and you don't want that
value to reflect any changes made by other owners of the object. You
will need to release the object when you are finished with it because
you are retaining the copy.
Weak
weak is similar to strong except that it won't increase the reference
count by 1. It does not become an owner of that object but just holds
a reference to it. If the object's reference count drops to 0, even
though you may still be pointing to it here, it will be deallocated
from memory.
This is a good website to learn about strong and weak for iOS 5.
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1
In addition to the above problem,your constrains of the SimpleTableCell is also incorrect:
You should go to the Main.storyboard and check it.(In Interface Builder Select the Compact Width and Compact Height Size Class)
The tableView:cellForRowAtIndexPath: code you're using is pretty old.
I'd suggest creating a custom UITableViewCell class, with properties for your labels, image, and buttons.
#interface MyTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *nick;
#property (nonatomic, weak) IBOutlet UILabel *comment;
#property (nonatomic, weak) IBOutlet UIImageView *avatar;
#property (nonatomic, weak) IBOutlet UIButton *sinvoto;
#property (nonatomic, weak) IBOutlet UIButton *ticket;
#end
In your storyboard, set that cell's class to your custom tableViewCell, and connect its IBOutlets to the storyboard cell's labels, image, and buttons. This will eliminate having to use tags.
Change the dequeueReusableCellWithIdentifier: call to:
MyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
This will always return a cell, so you will never have to check for nil.
Now you can directly set the cell's properties:
cell.avatar.image = [UIImage imageNamed:[[comentarios objectAtIndex:indexPath.row] avatar]];
cell.nick.text =[[comentarios objectAtIndex:indexPath.row] nick];
cell.comment.text = [[comentarios objectAtIndex:indexPath.row] comment];
Update:
This line (has to do with changing the keyboard) is unnecessary and can be removed:
[self reloadInputViews];
Is there a reason why you are using a UIViewController (with a tableView that you added), instead of simply using a UITableViewController?
The UITableViewController knows how to adjust its insets to account for top and bottom bars (and you would set its automaticallyAdjustsScrollViewInsets to YES).
After making the changes that Banning suggests, you may be ok. I can't see any other reason why the cells would be blank after scrolling.
If it's still happening, you should post your Comentario class, so we can see if an issue with that code is affecting the stored data.
I'm having issue trying to load a thumbnail from JSON into a UITableView cell. The cell's UI is a xib file. I'm not able to parse the thumbnail part of the JSON and display it in the table view. It's been a while since I did this (I tend to work on more games than typical iOS apps), and the last time I did it was a slightly different implementation.
JSON:
{
"data" :
[
{
"user_id" : "3",
"username" : "Alex Perez",
"avatar_url" : "http://mywebsite.com/images/alex_avatar.png",
"message" : "Hello there?"
},
{
"user_id" : "4",
"username" : "Jon Doe",
"avatar_url" : "http://mywebsite.com/images/john_avatar.png",
"message" : "I'm here now"
},
{
"user_id" : "2",
"username" : "Sam Givens",
"avatar_url" : "http://mywebsite.com/images/sam_avatar.png",
"message" : "Can we have a meeting around 2?"
},
....
And the data in the Data.h:
#import <Foundation/Foundation.h>
#interface Data : NSObject
#property (nonatomic, readwrite) int user_id;
#property (nonatomic, strong) NSString *username;
#property (nonatomic, strong) NSString *avatar_url;
#property (nonatomic, strong) NSString *message;
- (void)loadWithDictionary:(NSDictionary *)dict;
#end
Data.m:
#import "Data.h"
#implementation Data
- (void)loadWithDictionary:(NSDictionary *)dict {
self.user_id = [[dict objectForKey:#"user_id"] intValue];
self.username = [dict objectForKey:#"username"];
self.avatar_url = [dict objectForKey:#"avatar_url"];
self.message = [dict objectForKey:#"message"];
}
#end
Here is I'm running into issues when declaring the property and assigning the property to the data, so then it can then be passed to the View Controller that is going to display it. I'm getting the compiler warning Incompatible pointer types assigning to UIImage * from NSString*. I don't understand why Xcode isn't complaining about the other properties like the UILabel and the UITextView.
Cell.m
#import "Cell.h"
#interface Cell ()
#property (nonatomic) int userID;
// UIImageView property created from Interface Builder
#property (strong, nonatomic) IBOutlet UIImageView *avatarImage;
#property (nonatomic, strong) IBOutlet UILabel *usernameLabel;
#property (nonatomic, strong) IBOutlet UITextView *messageTextView;
#end
#implementation Cell
- (void)loadWithData:(Data *)data {
self.userID = data.user_id;
// Here I get "Incompatible pointer types assigning to UIImage * from NSString*
self.avatarImage.image = data.avatar_url;
self.usernameLabel.text = data.username;
self.messageTextView.text = data.message;
}
#end
Finally the MessagesViewController where it is displayed:
#interface MessagesViewController ()
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#property (nonatomic, strong) NSMutableArray *loadedChatData;
#end
#implementation MessagesViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.loadedChatData = [[NSMutableArray alloc] init];
[self loadJSONData];
}
- (void)loadJSONData {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"json"];
NSError *error = nil;
NSData *rawData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
id JSONData = [NSJSONSerialization JSONObjectWithData:rawData options:NSJSONReadingAllowFragments error:&error];
[self.loadedChatData removeAllObjects];
if ([JSONData isKindOfClass:[NSDictionary class]]) {
NSDictionary *jsonDict = (NSDictionary *)JSONData;
NSArray *loadedArray = [jsonDict objectForKey:#"data"];
if ([loadedArray isKindOfClass:[NSArray class]])
{
for (NSDictionary *chatDict in loadedArray)
{
Data *chatData = [[Data alloc] init];
[chatData loadWithDictionary:chatDict];
[self.loadedChatData addObject:chatData];
}
}
}
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
Cell *cell = nil;
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil];
cell = (Cell *)[nib objectAtIndex:0];
}
Data *data = [self.loadedChatData objectAtIndex:[indexPath row]];
[cell loadWithData:data];
return cell;
}
U have to modify the error line and use it as :
self.avatarImage.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:data.avatar_url]]];
Create a custom class for the nib and then place the certain code in it to load the image from direct URL ... this works
var stringUrl = "http://mywebsite.com/images/alex_avatar.png"
var url: NSURL = NSURL(string: stringUrl)!;
self.imageView1.sd_setImageWithURL(url, placeholderImage: UIImage(named: "no_image_small.png"));
Try the Below code, it may help you.
NSURL *url = [NSURL URLWithString:#"http://mywebsite.com/images/alex_avatar.png"];
UIImage *thumbnail = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
if (thumbnail == nil) {
thumbnail = [UIImage imageNamed:#"noimage.jpg"] ; //if no image get from url mean show a dummy one
}
CGSize itemSize = CGSizeMake(80, 80); //your own size can replace with 80
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[thumbnail drawInRect:imageRect];
cell.thumbnailImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
If one had a NSString that needed a userid to be used as a URL for a request:
And one had a NSMutableArray that he wanted to Queue into the above call one at a time? So basically make 3 calls of NSString from the NSMutableArray .
One can check multiple UITableView cells and once completed I can index which cell rows were pushed. That is what userIDArray is used for now I want to make a call with the userID's I got back from userIDArray.
for (NSDictionary* userIDDict in userIDArray)
{
userIDArray = [[NSMutableArray alloc] init]; //I put this line in my viewdidload
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
}
UserIDArray is the NSMutableArray .
This would be the NSLog from the NSMutableArray The Integer would be 1, 2 and 3.
UserID: 1
UserID: 2
UserID: 3
So in other words I would like to take the results from my NSMultiTableArray 1,2 and 3 to use within the NSString :
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=1"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=2"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=3"];
So I would make the first call and wait for a result, and then the second and finally the third.
Can this be done? I have search this link about Queues and this one but I am unsure if those are what I need?
UserDetailViewController.h file:
#interface UserDetailViewController : UIViewController <UITableViewDelegate>{
long long expectedLength;
long long currentLength;
UITableView *userTableView;
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSArray *userIDJson;
#property (strong, nonatomic) NSDictionary *userIDDict;
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#property (nonatomic, strong) NSMutableArray *userIDArray;
#property (nonatomic) NSInteger currentUserIndex;
#end
UserDetailViewController.m file:
#interface UserDetailViewController ()
#end
#implementation UserDetailViewController
#synthesize userIDJson;
#synthesize userIDDict;
#synthesize checkedIndexPath;
#synthesize userIDArray;
#synthesize currentUserIndex;
- (void)viewDidLoad
{
[super viewDidLoad];
userIDArray = [[NSMutableArray alloc] init];
[self.navigationController setNavigationBarHidden:NO];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//return self.loadedSearches.count;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.userIDJson.count;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
}
cell.textLabel.text = self.userIDJson[indexPath.row][#"UserName"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *userStringIndex = [self.userIDJson objectAtIndex:indexPath.row];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[userIDArray addObject:userStringIndex];
}
else
{
thisCell.accessoryType = UITableViewCellAccessoryNone;
[userIDArray removeObject:userStringIndex];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < userIDArray.count) {
NSNumber* userID = [[userIDArray objectForIndex:currentUserIndex]objectForKey:#"UserID"];
//Make the actual request here, and assign the delegate.
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=%#",userID];
self.currentUserIndex++;
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:userProfile]];
NSString *userResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSURL *url = [[NSURL alloc] initWithString: userProfile];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
userIDJson = [NSJSONSerialization JSONObjectWithData:dataURL
options:kNilOptions
error:&error];
}
}
for (userIDDict in userIDArray)
{
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
NSLog(#"%#", userID);
NSArray* userName = [userIDDict objectForKey:#"UserName"];
}
NSURLConnection can take a delegate through the constructor initWithRequest:delegate:. So you need the object that makes the calls conform to that protocol, I'll assume it's a UIViewController. You can use one of the required methods in the delegate to fire up the next request.
For example, assume you have property to indicate the current index.
#property (nonatomic) NSInteger currentUserIndex;
Then in the place that will fire the first request, make the call for the first user. In some delegate method, say connectionDidFinishLoading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < self.userIDArray.count) {
NSNumber* userID = [[self.userIDArray objectAtIndex:self.currentUserIndex] objectForKey:#"UserID"];
self.currentUserIndex++;
//Make the actual request here, and assign the delegate.
}
}
Of course, if your connection calls don't have to be synchronous, you can do it in an easier way.