problems with the UITableView - please advice - ios

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"];

Related

How to implement search option with webservice url in ios, using objective C

I'm getting data from a web service.If we pass any string through service url, then it will returns data according to it.I have implemented and display data in a tableview . now what I want is to implement search option for it. so I used uisearchcontroller and to do that.but it is not working well.I mean if we send letter 'y' for the web service, it will return all the results that starts from y. this is my code.
- (void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.scopeButtonTitles = #[NSLocalizedString(#"ScopeButtonCountry", #"Airport"), NSLocalizedString(#"ScopeButtonCapital", #"AirportCode")];
self.searchController.searchBar.delegate = self;
//self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.mtableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
[self.searchController.searchBar sizeToFit];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)getAirports:(NSString *)needeedString
{
airportList = nil;
needeedString = [NSString stringWithFormat:#""];
NSString *apiKey = [NSString stringWithFormat:#"some api"];
NSString *fullUrl = [NSString stringWithFormat:#"someurl%#%#",apiKey,needeedString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:fullUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSArray *result = (NSArray *)responseObject;
airportList = [NSMutableArray array];
for (NSDictionary *all in result)
{
Details *d1 = [Details new];
d1.airport = [all objectForKey:#"Airport"];
[airportList addObject:d1];
[self.mtableView reloadData];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString == nil || [searchString isEqual: #""]) {
[self getAirports:#""];
[self.mtableView reloadData];
}
[self getAirports:searchString];
[self.mtableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [airportList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ci"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"ci"];
}
Details *newDetails = [airportList objectAtIndex:indexPath.row];
cell.textLabel.text = newDetails.airport;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Details *newDetails = [airportList objectAtIndex:indexPath.row];
NSString *selectedText = newDetails.airport;
[[NSUserDefaults standardUserDefaults] setObject:selectedText forKey:#"st"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self dismissViewControllerAnimated:YES completion:nil];
}
Please find the below changes I have made ,hope it will work
- (void)getAirports:(NSString *)needeedString
{
airportList = nil;
needeedString = [NSString stringWithFormat:#""];
NSString *apiKey = [NSString stringWithFormat:#"some api"];
NSString *fullUrl = [NSString stringWithFormat:#"someurl%#%#",apiKey,needeedString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:fullUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSArray *result = (NSArray *)responseObject;
airportList = [NSMutableArray array];
for (NSDictionary *all in result)
{
Details *d1 = [Details new];
d1.airport = [all objectForKey:#"Airport"];
[airportList addObject:d1];
//remove reload data method from here because it will reload your table on each iteration
}
dispatch_async(dispatch_get_main_queue(), ^{
//reload on main thread
[self.mtableView reloadData];
});
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString != nil && ![searchString isEqual: #""]) {
[self getAirports:searchString];
}
//here there is no need to reload
//also changed condition
}
Call reload in dispatch main queue:
dispatch_async(dispatch_get_main_queue(), ^{
[self.mtableView reloadData];
});
I guess In method
- (void)getAirports:(NSString *)needeedString
remove
[self.mtableView reloadData];
outside the for loop
and you can call reloadData like
self.mtableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES

UITableView cellForRowAtIndexPath not getting called

I know that the cellForRowAtIndexPath method isn't being called because I never see the NSLog messages inside of it. I have set the dataSource and delegate attributes of the UITableView and I also have declared UITableViewDelegate and UITableViewDataSource in the header file. What am I missing?
- (void)viewDidLoad {
[self.view setBackgroundColor:[UIColor grayColor]];
tableData = [[NSMutableArray alloc] init];
matchesForUser = [[NSMutableArray alloc] init];
sortedFirstArray = [[NSArray alloc] init];
sortedSecondArray = [[NSArray alloc] init];
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - 20) style:UITableViewStylePlain];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:_tableView];
countUsers = 0;
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
}];
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
backToMap = [[UIButton alloc] initWithFrame:CGRectMake(80, 518, 160, 30)];
backToMap.backgroundColor = [UIColor colorWithRed:33.0f/255.0f green:156.0f/255.0f blue:41.0f/255.0f alpha:1.0f];
[backToMap addTarget:self action:#selector(dismiss) forControlEvents:UIControlEventTouchUpInside];
[backToMap setTitle:#"BACK TO MAP" forState:UIControlStateNormal];
[self.view addSubview:backToMap];
}
- (void)dismiss {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSString *username = [[sortedFirstArray objectAtIndex:indexPath.row] stringByAppendingString:#" "];
NSString *matchAmount = [sortedSecondArray objectAtIndex:indexPath.row];
NSLog(#"***username***");
NSLog(username);
NSLog(#"***matchamount***");
NSLog(matchAmount);
cell.textLabel.text = [username stringByAppendingString:matchAmount];
return cell;
}
Try doing the following things
1.) Register your tableView like
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"SimpleTableItem"];
2.) Then Add [_tableView reloadData]; just below
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
Inside if (!error) part..
So your Updated Code must look like
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
[_tableView reloadData];
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
}];
1) Here you do need to use countUsers = 0;If you need than you need to increment the value inside for loop by 1.Otherwise it will overwrite the value at index 0 every time.
2) You are using background calling method to fetch data.So it will take time to fetch data and control will go further and execute following code.But At that time matchesForUser array is empty, and dictionary is also empty.So in cell it won't display anything and you will not see NSLOG from cell.
Instead of this
ini
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
3) Try with this,
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
[tableData addObject:[object valueForKey:#"username"]];
[matchesForUser addObject:[object valueForKey:#"matches"]];
}
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
[_tableView reloadData];
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
});
}];
Did you reload the Tableview in ViewDidLoad? like
[_tableView reloadData];
Reload the table again after
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
[_tableView reloadData];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
The count is 0? you can type NSLog("%#", #(tableData.count)); or just return 1; for test.
UITableView send the tableView:numberOfRowsInSection: first, if the method return 0. it will not call the cellForRowAtIndexPath.
And as #PiyushSharma mentioned, you should Register your tableView.

tableview reloadData not working after successful login / AFNetworking

I'm using the below code in my ViewController.m to log a user in to my app. However on the following ViewController (AccountViewController), I have a tableView. Upon successful login, I want to reload/populate the data in the tableView, but instead after a successful login, I get an empty table. I've put reloadData in viewWillAppear at the top of MyAccountViewController. See below. Not sure why it's doing this, as when I navigate from AccountViewController to another screen and back, the table is populated. Is my AFNetworking bit causing the table not to populate for some reason?
ViewController.m
[DIOSUser userLoginWithUsername:_userField.text
andPassword:_passField.text
success:^(AFHTTPRequestOperation *op, id response) {
// Saving to keychain/NSUserDefaults
NSDictionary *diosSession = [[DIOSSession sharedSession] user];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:diosSession] forKey:#"diosSession"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[DIOSSession sharedSession] getCSRFTokenWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *csrfToken = [NSString stringWithUTF8String:[responseObject bytes]];
[[NSUserDefaults standardUserDefaults] setObject:csrfToken forKey:#"diosToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failure handler
}];
wrongLogin.hidden = YES;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MyAccountViewController *yourViewController = (MyAccountViewController *)[storyboard instantiateViewControllerWithIdentifier:#"MyAccount"];
[self.navigationController pushViewController:yourViewController animated:YES];
[self.activityIndicatorViewOne stopAnimating];
self.activityIndicatorViewOne.hidden = YES;
NSLog(#"Success!");}
failure:^(AFHTTPRequestOperation *op, NSError *err) { NSLog(#"Fail!"); wrongLogin.hidden = NO; }
];
AccountViewController.m
- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView reloadData];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(ReloadDataFunction:)
name:#"refresh"
object:nil];
[self.tableView reloadData];
self.descripData = [[NSMutableArray alloc] init];
UIBarButtonItem *flipButton = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:#"logouticon4.png"]
// initWithTitle:#"Logout"
style:UIBarButtonItemStylePlain
target:self
action:#selector(flipView)];
self.navigationItem.rightBarButtonItem = flipButton;
[flipButton release];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[self.navigationItem setHidesBackButton:YES animated:YES];
refreshControl = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
// Do any additional setup after loading the view.
self.storageData = [[NSMutableDictionary alloc] init];
userName.text = [[[DIOSSession sharedSession] user] objectForKey:#"name"];
//emailAddress.text = [[[DIOSSession sharedSession] user] objectForKey:#"mail"];
NSLog(#"%#", [[DIOSSession sharedSession] user]);
// DIOSView *view = [[DIOSView alloc] init];
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"storeditems" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.descripData = [responseObject mutableCopy];
NSLog(#"%#",self.descripData);
// [self.tableView reloadData];
// [HUD hide:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
[DIOSNode nodeIndexWithPage:#"0" fields:#"title" parameters:[NSArray arrayWithObjects:#"storage_item", nil] pageSize:#"20" success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Nodes retrieved!");
__block int iCount = 0;
for (id object in responseObject) {
// NSLog(#"adding object!");
[self.storageData setObject:(NSDictionary *)object forKey:[NSString stringWithFormat:#"%d",iCount]];
iCount++;
[self.tableView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.storageData count] > 0 && self.descripData.count > 0)
{
return [self.descripData count];
}
else
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = #"StorageItemTableViewCell";
StorageItemTableViewCell *cell = (StorageItemTableViewCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StorageItemTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.storageData.count > 0 && self.descripData.count > 0) {
noitemsView.hidden = YES;
cell.cellCountLabel.text = [NSString stringWithFormat:#"%i", indexPath.row+1];
NSDictionary *title = [self.descripData objectAtIndex:indexPath.row];
[[cell itemName] setText:[title objectForKey:#"node_title"]];
NSDictionary *node = [self.descripData objectAtIndex:indexPath.row];
[[cell itemDescrip] setText:[node objectForKey:#"body"]];
NSDictionary *value = [self.descripData objectAtIndex:indexPath.row];
[[cell valueLabel] setText:[value objectForKey:#"storeditemvalue"]];
NSLog(#"%#", self.descripData);
NSDictionary *quantity = [self.descripData objectAtIndex:indexPath.row];
[[cell quantityLabel] setText:[quantity objectForKey:#"numberofitemstored"]];
NSLog(#"%#", self.descripData);
NSString *secondLink = [[self.descripData objectAtIndex:indexPath.row] objectForKey:#"photo"];
[cell.itemPhoto sd_setImageWithURL:[NSURL URLWithString:secondLink]];
NSLog(#"%#",secondLink);
}
else {
noitemsView.hidden = NO;
}
return cell;
}
You have a "refresh" observer, but it calls a function you haven't shown here. You set your data it looks like with this:
for (id object in responseObject) {
// NSLog(#"adding object!");
[self.storageData setObject:(NSDictionary *)object forKey:[NSString stringWithFormat:#"%d",iCount]];
iCount++;
[self.tableView reloadData];
}
but because that is in viewDidLoad, it is only called once, BEFORE viewWillAppear. You need to fill self.storageData and self.descripData in a separate function, then call THAT function from viewWillAppear, or using your NSNotificationCenter notification from the previous VC.

what is the best place to reload data in UITableView or UICollectionView in ios

I'm using AFNetworking to load data.In my case, I load data into a collectionview.
I load data inside my custom method and inside that I reload collectionview data.
And I call this method in viewDidLoad method. Why I'm asking this is, it takes more time to load data. I thought this is because of the place I reload collectionview data.I want to know ,can I speed up the process by reloading collectionview data in another method like viewwillappear or any other.hope your help.thank you
- (void)viewDidLoad {
[super viewDidLoad];
[self loadcategoryData];
SWRevealViewController *revealcontroller = self.revealViewController;
if (revealcontroller) {
[self.sideBarbutton setTarget:self.revealViewController];
[self.sideBarbutton setAction:#selector(revealToggle:)];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
// Do any additional setup after loading the view.
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)viewDidAppear:(BOOL)animated
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)viewDidDisappear:(BOOL)animated
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)loadcategoryData
{
post = nil;
NSString *mainurl = [NSString stringWithFormat:#"some url"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager GET:mainurl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
posts = (NSDictionary *)responseObject;
post = [NSMutableArray array];
for(NSDictionary *all in posts)
{
Categories *category = [Categories new];
category.title = [all objectForKey:#"catname"];
category.firsturl = [all objectForKey:#"url"];
[self.maincollectionView reloadData];
//call for images
imagespost = nil;
NSString *imageUrl = [NSString stringWithFormat:#"%#", category.firsturl];
AFHTTPRequestOperationManager *managerone = [AFHTTPRequestOperationManager manager];
[managerone GET:imageUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
imagesposts = (NSDictionary *)responseObject;
NSArray *resultone = [imagesposts objectForKey:#"posts"];
imagespost = [NSMutableArray array];
if ([resultone count]) {
NSDictionary *firstpost = resultone[0];
// Categories *newmogocat = [Categories new];
NSDictionary *thumbnail_images = [firstpost objectForKeyedSubscript:#"thumbnail_images"];
NSDictionary *thumbnail = [thumbnail_images objectForKey:#"thumbnail"];
category.imageOneUrl = [NSString stringWithFormat:#"%#",[thumbnail objectForKey:#"url"]];
// NSLog(#"%#", newmogocat.imageOneUrl);
// [imagespost addObject:newmogocat];
[post addObject:category];
[self.maincollectionView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
// UIAlertView *erroralert = [[UIAlertView alloc] initWithTitle:#"Something Wrong!" message:[NSString stringWithFormat:#"%#", error.localizedDescription] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
// [erroralert show];
}];
}
} failure:^(AFHTTPRequestOperation *operation, NSError * responseObject) {
}];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [post count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CategoryCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellidentifier" forIndexPath:indexPath];
// cell.layer.borderWidth = 2.0f;
cell.layer.masksToBounds = NO;
cell.layer.cornerRadius = 5.0;
cell.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.layer.shadowOffset = CGSizeMake(0, 1);
cell.layer.shadowRadius = 4.0;
cell.layer.shadowColor = [UIColor darkGrayColor].CGColor;
[cell addSubview:cell.maintitleLabel];
Categories *cat = [post objectAtIndex:indexPath.row];
[self.maincollectionView reloadInputViews];
cell.maintitleLabel.text = [NSString stringWithFormat:#" %# ", cat.title];
[cell.maintitleLabel sizeToFit];
NSString *mainstring = [NSString stringWithFormat:#"%#", cat.imageOneUrl];
NSURL *url = [NSURL URLWithString:mainstring];
//
[cell.mainImageView setImageWithURL:url placeholderImage:nil];
//
return cell;
}
The earliest you can begin to load your data is in the init method. But to be honest most of the time they get called so quickly after eachother you probably wont even notice the difference. But if you were interested, just wack it in here:
- (id)init
{
self = [super init];
if (self)
{
[self loadcategoryData];
}
return self;
}
Also I don't know how much data your downloading, but if you are loading a long list and it is taking a long time then maybe you should consider doing "paging" (i.e. only downloading a sub section of the data and then requesting more as the user scrolls down the page.

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

Resources