App Crashes when ReloadData done for the tableView - ios

I am using the following code to reload my tableView when its done adding all the data to my Mutable Arrays, but the app always crashes
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Spinner Add while waiting
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.frame = CGRectMake(147, 10, 25, 25);
[self.tableView addSubview:spinner];
[spinner startAnimating];
operationQueue = [[NSOperationQueue alloc] init];
usersFirstName = [[NSMutableArray alloc] init];
usersLastName = [[NSMutableArray alloc] init];
usersAvatar = [[NSMutableArray alloc] init];
NSString *urlstring = [NSString stringWithFormat:#"https://www.test.com/scribble/%#/",scribbleId];
NSURL *url = [NSURL URLWithString:urlstring];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
users = JSON[#"users_favored"];
if (users.count > 0) {
NSUInteger count = [users count];
for (NSUInteger i =0; i<count; i++) {
NSString *urlString = [NSString stringWithFormat:#"https://www.test.com%#",[users objectAtIndex:i]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *requestUser = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestUser success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
if (i == 0) {
usersFirstName = [JSON[#"first_name"] mutableCopy];
usersLastName = [JSON[#"last_name"] mutableCopy];
usersAvatar = [JSON[#"user_avatar"] mutableCopy];
}else{
[usersFirstName addObjectsFromArray:JSON[#"first_name"]];
[usersLastName addObjectsFromArray:JSON[#"last_name"]];
[usersAvatar addObjectsFromArray:JSON[#"user_avatar"]];
}
if (i == count-1) {
[self.tableView reloadData];
[spinner stopAnimating];
[spinner removeFromSuperview];
}
}failure:nil];
[operationQueue addOperation:operation];
}
}else{
self.navigationItem.title = #"No Favors";
[spinner stopAnimating];
[spinner removeFromSuperview];
}
} failure:nil];
[operationQueue addOperation:operation];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return usersFirstName.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableFavorIdentifier = #"FavorCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableFavorIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableFavorIdentifier];
}
NSString *firstName = [usersFirstName objectAtIndex:indexPath.row];
NSString *lastName = [usersLastName objectAtIndex:indexPath.row];
NSString *avatar = [usersAvatar objectAtIndex:indexPath.row];
NSString *userFullName = [NSString stringWithFormat:#"%# %#",firstName,lastName];
UIImageView *userAvatar = (UIImageView *)[cell viewWithTag:100];
if ([avatar length ] > 0) {
NSString *img = [#"https://dtest_media_and_assets.s3.amazonaws.com/" stringByAppendingString:avatar];
[userAvatar setImageWithURL:[NSURL URLWithString:img] placeholderImage:[UIImage imageNamed:#"scribble.png"]];
}else{
userAvatar.image = [UIImage imageNamed:#"scribble.png"];
}
userAvatar.layer.cornerRadius = 4.0;
userAvatar.clipsToBounds = YES;
UILabel *userNameLabel = (UILabel *)[cell viewWithTag:101];
userNameLabel.text = userFullName;
return cell;
}
The error it gives is
2013-03-15 16:37:08.910 test[19547:c07] -[__NSCFString count]: unrecognized selector sent to instance 0x8679c80
2013-03-15 16:37:08.911 test[19547:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString count]: unrecognized selector sent to instance 0x8679c80'
*** First throw call stack:
(0x1cdf012 0x169fe7e 0x1d6a4bd 0x1ccebbc 0x1cce94e 0x143d7 0x7c8548 0x7cb224 0x68f952 0x68f2dc 0x140d7 0x281d2 0x29569 0x2f9553f 0x2fa7014 0x2f977d5 0x1c85af5 0x1c84f44 0x1c84e1b 0x21bb7e3 0x21bb668 0x5e3ffc 0x200d 0x1f35)
libc++abi.dylib: terminate called throwing an exception
Edit
everything works just fine when I use this instead
[usersFirstName addObject:JSON[#"first_name"]];
[usersLastName addObject:JSON[#"last_name"]];
[usersAvatar addObject:JSON[#"user_avatar"]];
[self.tableView reloadData];
if (i == count-1) {
[spinner stopAnimating];
[spinner removeFromSuperview];
}

try the same with that function:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"usersFirstName is of type %#", NSStringFromClass([usersFirstName class]));
return [usersFirstName count];
}
I guess you have to replace:
if (i == 0) {
usersFirstName = [JSON[#"first_name"] mutableCopy];
usersLastName = [JSON[#"last_name"] mutableCopy];
usersAvatar = [JSON[#"user_avatar"] mutableCopy];
}else{
[usersFirstName addObjectsFromArray:JSON[#"first_name"]];
[usersLastName addObjectsFromArray:JSON[#"last_name"]];
[usersAvatar addObjectsFromArray:JSON[#"user_avatar"]];
}
with just:
[usersFirstName addObject:JSON[#"first_name"]];
[usersLastName addObject:JSON[#"last_name"]];
[usersAvatar addObject:JSON[#"user_avatar"]];

The issue is that this:
users = JSON[#"users_favored"];
Returns an NSString, when it looks you are expecting an NSArray.
Verify this using:
users = JSON[#"users_favored"];
NSLog(#"users is of type %#", NSStringFromClass([users class]));
Something is either wrong with your assumption or the JSON is broken.

Related

UITableView taking lots of time to bind data

I am using UITableView and after calling web service I am creating cells and binding data. Web service fetching data speed is very good and fast but i checked it's taking time to bind cells to UITableView.My code is -
.m file
#pragma mark tableViewDelegate Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//return ([team1Arr count]+1);
if (isFiltered) {
return [filteredMySquareArr count];
}
else
return [mySquareArr count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
UILabel *squareNameLbl = [[UILabel alloc] initWithFrame:CGRectMake(25.0, 7.0, 300, 25)];
[squareNameLbl setFont:[UIFont systemFontOfSize:15]];
UILabel *descLbl = [[UILabel alloc]initWithFrame:CGRectMake(25.0, 32.0, 285.0, 13.0)];
[descLbl setFont:[UIFont systemFontOfSize:12]];
descLbl.textColor = [UIColor colorWithRed:72.0f/255 green:180.0f/255 blue:71.0f/255 alpha:1.0f];
UIImageView *lockImage = [[UIImageView alloc] initWithFrame:CGRectMake(10, 15, 10, 10)];
NSString *accessTypeStr;
if (isFiltered) {
//cell.textLabel.text = [filteredMySquareArr objectAtIndex:indexPath.row];
squareNameLbl.text = [filteredMySquareArr objectAtIndex:indexPath.row];
descLbl.text =[NSString stringWithFormat:#"Located within %.2f miles", [[filteredMySquareDescArr objectAtIndex:indexPath.row] doubleValue]];
accessTypeStr = [NSString stringWithFormat:#"%#",[filteredAccessTypeArr objectAtIndex:indexPath.row]];
if ([accessTypeStr isEqualToString:#"private"]) {
lockImage.image = [UIImage imageNamed:#"lock.png"];
}
}
else
{
//cell.textLabel.text = [mySquareArr objectAtIndex:indexPath.row];
squareNameLbl.text = [mySquareArr objectAtIndex:indexPath.row];
descLbl.text =[NSString stringWithFormat:#"Located within %.2f miles",[[mySquareDescArr objectAtIndex:indexPath.row] doubleValue]];
accessTypeStr = [NSString stringWithFormat:#"%#",[accessTypeArr objectAtIndex:indexPath.row]];
if ([accessTypeStr isEqualToString:#"private"]) {
lockImage.image = [UIImage imageNamed:#"lock.png"];
}
}
cell.backgroundColor = [UIColor clearColor];
[cell addSubview:squareNameLbl];
[cell addSubview:descLbl];
[cell addSubview:lockImage];
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
[image setImage:[UIImage imageNamed:#"arrow_list.png"]];
cell.accessoryView = [[UIImageView alloc]initWithFrame:CGRectMake(260.0, 7.0, 10, 20)];
[cell.accessoryView addSubview:image];
});
// });
//cell.accessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"arrow_list.png"]];
return cell;
}
WebService
#pragma mark - Webservice Methods
-(void)fetchUpcomingSquares
{
NSString *post = [NSString stringWithFormat:#"access_token=%#&page=0",globalAccessToken];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu",(unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#upcoming_squares",GLOBALURLDOMAIN]]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURLResponse *response;
NSError *error =nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"responsedata =%#",responseData);
if(error)
{
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"HTTP Error: %d %#", httpResponse.statusCode, error);
return;
}
NSLog(#"Error %#", error);
[hud hide:YES];
return;
}
if (responseData == NULL) {
AppDelegate *appdel = [[UIApplication sharedApplication]delegate];
[hud hide:YES];
[appdel alertError];
}
else
{
NSDictionary *parsingResultLogin = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSLog(#"parsingResultLogin = %#",parsingResultLogin);
if ([#"-1" isEqualToString:[[parsingResultLogin objectForKey:#"result"]objectForKey:#"error_code"]]) {
NSLog(#"%#",[[parsingResultLogin objectForKey:#"result"]objectForKey:#"error_message"]);
[self showAlertWithMessage:[NSString stringWithFormat:#"%#",[[parsingResultLogin objectForKey:#"result"]objectForKey:#"error_message"]]];
[hud hide:YES];
}
else
{
NSLog(#"Valid ID");
NSDictionary *result= [parsingResultLogin objectForKey:#"result"];
//NSLog(#"result = %#", result);
squareList = [result objectForKey:#"squares"];
NSLog(#"squareList = %#", squareList);
for (NSDictionary *sq in squareList) {
[mySquareArr addObject:[sq objectForKey:#"square_name"]];
[mySquareDescArr addObject:[sq objectForKey:#"max_distance"]];
[accessTypeArr addObject:[sq objectForKey:#"access_type"]];
}
[self.mySquareTblView reloadData];
[hud hide:YES];
}
}
});
NSLog(#"access Type =%#",accessTypeArr);
}
I think it's pretty clear. You're not using your cell identifier on this line of code:
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:nil];
You should do it like this:
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
I used bellow code and it's working fine
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];

how to reload table view when I'm in a class?

I have a table view on InquiryViewController that I want to be reloaded when I click the update status button. The update status button is a JSON that gets the status of a message.
Here's the code:
-(BOOL)getMessageStatus : (NSMutableArray *)emails : (UIAlertView *)alert : (UIProgressView *)progress : (InquiryLogViewController *)controller
{
_emailsInApi = [[NSArray alloc]init];
_emailsInApi = [[DBManager getSharedInstance]arrayOfEmails];
NSMutableArray *newArrayEmail = [[NSMutableArray alloc]init];
NSString *arrayEmail =#"";
for(int i = 0; i<[_emailsInApi count]; i++){
arrayEmail = [_emailsInApi objectAtIndex:i];
[newArrayEmail addObject:arrayEmail];
}
NSURL *url = [NSURL URLWithString:#"http://www.url.com/API/2.0/message.php"];
NSDictionary *params =#{#"api_key":#"APIKEYIOS",#"action":#"get-message-status",#"email":newArrayEmail};
NSLog(#"params: %#",params);
NSData *paramsData = [NSJSONSerialization dataWithJSONObject:params
options:NSJSONWritingPrettyPrinted
error:nil];
NSString *paramsString = [[NSString alloc]initWithData:paramsData encoding:NSUTF8StringEncoding];
paramsString = [paramsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
paramsString = [paramsString stringByReplacingOccurrencesOfString:#"%5C" withString:#""];
NSString *post = [NSString stringWithFormat:#"params=%#", paramsString];
NSData *sendData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:sendData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
if (!error)
{
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"response...... = %#", responseString );
//get data frm response
self.responseData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.responseArray = [self.responseData objectForKey:#"data"];
for(NSDictionary *items in self.responseArray)
{
Inquiry *inq = [[Inquiry alloc]init];
inq.email = [items objectForKey:#"to_email"];
inq.status = [items objectForKey:#"status_id"];
[emails addObject:inq];
}
float newProg = (float)1 - (float)[emails count] / (float)5;
dispatch_async(dispatch_get_main_queue(), ^{
[progress setProgress:newProg animated:YES];
});
dispatch_async(dispatch_get_main_queue(), ^{
[[DBManager getSharedInstance]updateInquirylog:emails];
});
dispatch_async(dispatch_get_main_queue(), ^{
controller.arrayOfEmails = [[DBManager getSharedInstance]loadInquiries];
[controller.tableViews reloadData];
});
dispatch_async(dispatch_get_main_queue(), ^{
[alert dismissWithClickedButtonIndex:0 animated:YES];
});
}
else
{
self.alert = [[UIAlertView alloc] initWithTitle:nil message:error.localizedDescription delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
self.responseData = nil;
[alert show];
}
}];
[task resume];
return YES;
}
My problem here is in: [controller.tableViews reloadData];
It doesn't reload my table. Why? Help me please. Thank you
EDIT: This json is in a class
Ok I'm sorry. I forgot to include my table view method.
Here it is:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID =#"Cell";
tableCellOfInquiryLog *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (tableView == self.searchDisplayController.searchResultsTableView){
if(cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle]loadNibNamed:#"searchCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
Inquiry *inquiry = [searchResult objectAtIndex:indexPath.row];
cell.sInquiry_id.text =[NSString stringWithFormat:#"%d",inquiry.ID];
cell.sName.text = inquiry.name;
cell.sItem.text = inquiry.item_name;
cell.sDate.text = inquiry.dDate;
cell.status.layer.cornerRadius = 10;
if ([inquiry.status isEqual: #"1"]) {
cell.status.backgroundColor = [UIColor greenColor];
}
else if ([inquiry.status isEqual: #"2"]) {
cell.status.backgroundColor = [UIColor orangeColor];
}
else if ([inquiry.status isEqual: #"3"]) {
cell.status.backgroundColor = [UIColor redColor];
}
return cell;
}
else
{
if(cell == nil)
{
cell = [[tableCellOfInquiryLog alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
Inquiry *inquiry = [arrayOfInquiries objectAtIndex:indexPath.row];
cell.inquiry_id.text =[NSString stringWithFormat:#"%d",inquiry.ID];
cell.name.text = inquiry.name;
cell.item.text = inquiry.item_name;
cell.date.text = inquiry.dDate;
cell.status.layer.cornerRadius = 10;
if ([inquiry.status isEqual: #"1"]) {
cell.status.backgroundColor = [UIColor greenColor];
}
else if ([inquiry.status isEqual: #"2"]) {
cell.status.backgroundColor = [UIColor orangeColor];
}
else if ([inquiry.status isEqual: #"3"]) {
cell.status.backgroundColor = [UIColor redColor];
}
return cell;
}
return nil;
}
create a instance of your tableview and the add the given code in which ever method u want to add to [self.nameoftableview reloaddata]
if (indexPath.section ==1) {
cell = [tableView dequeueReusableCellWithIdentifier:section1identifier];
cell = nil;//here i have made it nil
if (!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:section1identifier];
data *newObj = [callingObj.itemslist objectAtIndex:indexPath.row];
UITextView *titlelabel = [[UITextView alloc]initWithFrame:CGRectMake(cell.frame.origin.x+5, cell.frame.origin.y-2, 320, 38)];
titlelabel.textColor = [UIColor redColor];
titlelabel.font= [UIFont fontWithName:#"Times New Roman" size:FONT_SIZE];
titlelabel.text = newObj.title;
titlelabel.scrollEnabled = NO;
titlelabel.editable = NO;
[cell.contentView addSubview:titlelabel];
desView = [[UITextView alloc]initWithFrame:CGRectMake(cell.frame.origin.x,cell.frame.origin.y+25 , 320, i + 160)];
desView.text = newObj.description;
desView.editable = NO;
desView.hidden = NO;
[cell.contentView addSubview:desView];
if (check == NO) {
desView.hidden = YES;
}
}
}
return cell;

problems with the UITableView - please advice

I have this piece of code and it should bring a ActivityIndicator (thats fine), then go out a query databases twice (looking at the logs it brings in all the correct info). I just STILL does not show up on the tableview and it is driving me crazy!! Can you if possible have a look over the code and see whats wrong - I have been on this for days now - please help!
[super viewDidLoad];
// create the activity indicator in the main queue
self.MainTableView.hidden = YES;
UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:ac];
[ac startAnimating];
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
self.table = [self.client tableWithName:#"notifications"];
self.rowitems = [[NSMutableArray alloc] init];
MSQuery *query = [self.table query];
query.fetchLimit = 3;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error)
{
self.rowitems = [items mutableCopy];
// we have the notifications and the barID in ROWITEMS array
// so lets make this into a dictionary so we can query it
// we need to run this next block of code 3 times, for the 3 bar ids we have got in ROWITEMS
//[self.TableView reloadData];
int a;
for (a = 0; a < 3; a++)
{
NSDictionary *apt = [self.rowitems objectAtIndex:a];
NSLog(#"%#", apt[#"barID"]);
NSDictionary *barIDDictionary = #{ #"myParam": apt[#"barID"]};
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
[self.client invokeAPI:#"photos" body:barIDDictionary HTTPMethod:#"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error );
}
else {
NSString *string = [NSString stringWithFormat:#"%#", [result objectForKey:#"rows"]];
NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *newStr = [completion substringFromIndex:1];
NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)];
[self.logoURL addObject:finalstring];
NSLog(#"%#",finalstring);
}
}];
}
}];
[self.MainTableView reloadData];
self.MainTableView.hidden = YES;
}
THIS IS ALL MY CODE THANKS
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) MSTable *table;
#property (nonatomic, strong) NSMutableArray *items;
#property (nonatomic, strong) NSMutableArray *logoURL;
#property (weak, nonatomic) IBOutlet UITableView *MainTableView;
#end
#implementation ViewController {
dispatch_queue_t MyQueue;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// create the activity indicator in the main queue
self.MainTableView.hidden = YES;
UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:ac];
[ac startAnimating];
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
self.table = [self.client tableWithName:#"notifications"];
self.rowitems = [[NSMutableArray alloc] init];
MSQuery *query = [self.table query];
query.fetchLimit = 3;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error)
{
self.rowitems = [items mutableCopy];
// we have the notifications and the barID in ROWITEMS array
// so lets make this into a dictionary so we can query it
// we need to run this next block of code 3 times, for the 3 bar ids we have got in ROWITEMS
[self.MainTableView reloadData];
int a;
for (a = 0; a < 3; a++)
{
NSDictionary *apt = [self.rowitems objectAtIndex:a];
NSLog(#"%#", apt[#"barID"]);
NSDictionary *barIDDictionary = #{ #"myParam": apt[#"barID"]};
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
[self.client invokeAPI:#"photos" body:barIDDictionary HTTPMethod:#"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error );
}
else {
NSString *string = [NSString stringWithFormat:#"%#", [result objectForKey:#"rows"]];
NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *newStr = [completion substringFromIndex:1];
NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)];
[self.logoURL addObject:finalstring];
NSLog(#"%#",finalstring);
[ac stopAnimating];
[self.MainTableView reloadData];
self.MainTableView.hidden = NO;
}
}];
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
NSDictionary *stress = [self.rowitems objectAtIndex:indexPath.row];
cell.textLabel.text = stress[#"content"];
// putting an image on a row
switch (indexPath.row) {
case 0:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(0)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
case 1:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(1)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
case 2:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(2)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
}
return cell;
}
#end
Looks like you need to call
[self.MainTableView reloadData];
self.MainTableView.hidden = NO;
inside Completion block
I think your Query is running asynchronously. All you need to do is to put your [tableView reloadData] in the block that runs after completion of the Query Block and make sure that you put the reloadData call inside a dispatch_async block.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Background work
dispatch_async(dispatch_get_main_queue(), ^{
// Update UI
[tableView reloadData];
}); });
Did you implement UITableViewDatasource and UITableViewDelegate protocols?
Implement required methods of this 2 protocols and link your MainTableView.
Programmatically:
MainTableView.datasource = self;
MainTableView.delegate = self;
Via storyboard:
UPD:
Try this code:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *stress = [self.rowitems objectAtIndex:indexPath.row];
cell.textLabel.text = [stress objectForKey:#"content"];

Scrolling issue Table View with JSON data

I'm parsing some data from a JSON-file located on my server to my Table View.
When I launch the app the app successfully downloads the data to my table view, but when I begin to scroll, the app crashes.
Here's my code:
#import "FirstViewController.h"
#import "YoutubePost.h"
#import "AFNetworking.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Videos", #"Videos");
self.tabBarItem.image = [UIImage imageNamed:#"newtab1"];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[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:#"http://my-website.com/link-to-json.php?name=Name&orderby=published"];
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 378;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"YoutubePost";
YoutubePost *cell = (YoutubePost *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"YoutubePost" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
cell.title.text = [movie objectForKey:#"title"];
NSURL *url = [[NSURL alloc] initWithString:[movie objectForKey:#"link"]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString * storyLink = [[_movies objectAtIndex: storyIndex] objectForKey:#"link"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:storyLink]];
NSString *formattedJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:[self.tweets objectAtIndex:indexPath.row] options:NSJSONWritingPrettyPrinted error:nil] encoding:NSUTF8StringEncoding];
NSLog(#"tweet:\n%#", formattedJSON);
}
#end
What is wrong? I see that the data successfully downloads to my custom Table View Cell, but every time I try to scroll down the app crashes. Please help me fix this.
Thanks.
Correct this:
// Initializing Data Source
//self.movies = [[NSArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"http://my-website.com/link-to-json.php?name=Name&orderby=published"];
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];
And in your YouTubePost Nib add Identifier "YouTubePost":
And also in your YouTubePost Nib select your title UILabel and in the inspector change from:
To:
Or Change:
To:
This will do the job.
Change the lines below:
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"YoutubePost" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Like this:
if (cell == nil)
{
UINib *nib = [UINib nibWithNibName:#"YoutubePost" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:#"YoutubePost"];
tableViewCell = [tableView dequeueReusableCellWithIdentifier:#"YoutubePost"];
}
It looks like you're not doing any checking for [NSNull null] in your JSON. It is possible that the following code will give you [NSNull null] instead of an NSDictionary:
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
You should filter these out before calling reloadData
Similarly, this line could also potentially return [NSNull null]:
cell.title.text = [movie objectForKey:#"title"];
You need to be prepared to handle that case. This may help you: Replace all NSNull objects in an NSDictionary

UI hanging on background rss parsing

I'm trying to create a simple rss reader. The code works okay, except the UI hangs when the feeds are being updated. I thought I cobbled together the code to get the feed and parse it on a background queue while updating the UI on the mainQueue, but the table hangs pretty badly. Code below:
-(void)refreshFeed2
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (NSString *feed in _feeds) {
// iterate over all feeds
NSLog(#"feed=%#", feed);
NSURL *url = [NSURL URLWithString:feed];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void)[conn initWithRequest:request delegate:self];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if ([data length] == 0 && error == nil) {
// handle empty response
} else if (error != nil) {
// handle error
NSLog(#"Error %#", [error localizedDescription]);
} else if ([httpResponse statusCode] == 200) {
// data present and no errors
[queue addOperationWithBlock:^{
// parse feed on queue
RXMLElement *rss = [RXMLElement elementFromXMLData:data];
RXMLElement *rssChild = [rss child:#"channel"];
RXMLElement* title = [rssChild child:#"title"];
NSArray* items = [[rss child:#"channel"] children:#"item"];
NSMutableArray* result=[NSMutableArray array];
for (RXMLElement *e in items) {
// iterate over the articles
RSSArticle* article = [[RSSArticle alloc] init];
article.sourceTitle = [title text];
article.articleTitle = [[e child:#"title"] text];
article.articleDescription = [[e child:#"description"] text];
article.articleUrl = [NSURL URLWithString: [[e child:#"link"] text]];
NSString *articleDateString = [[e child:#"pubDate"] text];
article.articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
if (article.articleUrl != NULL) {
[result addObject:article];
}
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// update table on mainQueue
for (RSSArticle *article in result) {
// iterate over articles
int insertIdx = [_allEntries indexForInsertingObject:article sortedUsingBlock:^(id a, id b) {
RSSArticle *entry1 = (RSSArticle *) a;
RSSArticle *entry2 = (RSSArticle *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:article atIndex:insertIdx];
[self.LeftTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationFade];
}
}];
}];
}
}];
// Stop refresh control
[refreshControl endRefreshing];
}
}
Code that calls refreshFeed2:
- (void)viewDidLoad {
[super viewDidLoad];
self.allEntries = [NSMutableArray array];
self.feeds = [NSArray arrayWithObjects:
#"http://feeds.washingtonpost.com/rss/politics",
#"http://rss.cnn.com/rss/cnn_allpolitics.rss",
#"http://www.npr.org/rss/rss.php?id=1012",
#"http://www.slatedigital.com/support/feeds/rss_kb.php?s=fd5aa35e773dc3177b85a2126583f002",
nil];
}
//add refresh control to the table view
refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self
action:#selector(refreshInvoked:forState:)
forControlEvents:UIControlEventValueChanged];
NSString* fetchMessage = [NSString stringWithFormat:#"Fetching Articles"];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:fetchMessage
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Helvetica" size:11.0]}];
[self.LeftTableView addSubview: refreshControl];
[self refreshInvoked:self forState:UIControlStateNormal];
}
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
NSOperationQueue *refreshQueue = [[NSOperationQueue alloc] init];
[refreshQueue addOperationWithBlock:^{
[self refreshFeed2];
}];
}
Any help?
Thanks!
Can you try this? replace
[self refreshInvoked:self forState:UIControlStateNormal];
by
[self performSelectorOnBackground:#selector(refreshFeed2) withObject:nil];
and replace the same instead of
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
[self performSelectorOnBackground:#selector(refreshFeed2) withObject:nil ];
}

Resources