I use UITableView to show the informations get for server. Create the connection in viewWillAppear: method:
- (void)viewWillAppear:(BOOL)animated {
//Create connection
}
And i put the received data into array : NSSArray *dataFromServer:
Then i want to show the data on each cell (some NSString object).
As the connection was release, i call [self.tableView reloadData] , but can't work.
So i'd like to know, how to make this?
The connection needs time to load data. So the correct is load the UI -> loading the data -> refresh the UI. So when the view was load, add the activityView is the good choice. And when the data finish loading, remove the activityView, and call [self.tableView reloadData];
The connection needs time to load data. So the correct is load the UI -> loading the data -> refresh the UI. So when the view was load, add the activityView is the good choice. And when the data finish loading, remove the activityView, and call [self.tableView reloadData];
Related
I have subclassed a CollectionView and using it using to display a collection of images in different categories. For example: Most Popular, Most Viewed. I access each category/page through a TabbarController.
The classes I have are:
Main class - MediaList - Base class for fetching and displaying media in a collection view depending on what type of media is requested.
SubClasses - MostPopular and MostViewed are both very light classes that inherit from the main class.
The problem is that when I move from MostPopular to MostViewed, the collection view initially displays the last category of pictures and then refreshes to the new...As a result you see a flicking effect.
Sample code from MediaList
- (void)viewDidLoad
{
[super viewDidLoad];
self.mediaCollection.dataSource = self;
self.mediaCollection.delegate = self;
[self getMedia];
}
(void) getMedia
{
NSLog(#"///////////////////////// GETTING MEDIA /////////////////////////");
XMLGenerator * sharedXmlGen = [XMLGenerator sharedXmlGenerator];
GlobalVars * sharedGlobalVars = [GlobalVars sharedGlobalVars];
sharedXmlGen.assetFlag = _contentFilter;
NSLog(#"The filter is: %#", _contentFilter);
[sharedXmlGen getPhotoVideoWithCallBackFunction:^{
[_mediaCollection performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}];
}
Sample code from SubClass (MostPopular):
- (void)viewDidLoad
{
[super setContentFilter:FILTER_POPULAR]; //Set the filter for the type of content
[super viewDidLoad];
// Do any additional setup after loading the view.
}
Two clarifications:
I should add that I am trying to re-use as much code as possible without having to create new views on the storyboard or controllers.
Because the media returned is very dynamic and can be updated regularly, I have had to reload my data (using getMedia) on viewDidAppear. This now means each selection of a particular page will result in the flickering when the new view is loaded...
Updates
- After further investigation it looks like this has nothing to do with subclassing the uicollectionview. The issue instead is just reloading data into the uicollectionview. To be sure, I just clicked on one of the two subclassed views. I also added a reload method to the viewdidAppear method just to see the issue get even worse. It's also much easier to see that the issue is that last set of images in the collection view initially displays the last category of pictures before the new one refreshes. Then once the collection is refreshed I get the flicker.
*Updates Oct 4 *
Starting to think my best solution is to display a waiting indicator and block the page while loading. I did try setting the uicollectionview to nil, and believe that will solve the problem as well, but not sure it will be straightforward to reset.
Although it may not be immediately apparent in the code above the root cause was actually the getMedia call. All of the subclassing etc. works perfectly fine.
Specifically having the reload method in the getMedia call and was creating the issue.
[_mediaCollection performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
Similar to this question: Adding subview, gets delayed?
But I don't think you can pushViewController in a separate thread so is this really impossible?
Here is what I'm trying to do:
I have a TableView and when a cell is pressed, I want to call
[self.view addSubview:LoadingView]
to display an overlay with a spinner. Then I call
self.navigationController.navigationBar.hidden = NO;
[self.navigationController pushViewController:newGameViewController animated:YES];
However, the subview only displays for a split second (~1-4 seconds after the cell selection occurs while it waits for the new viewcontroller to initialize).
Is there any way to get some sort of loading indicator to occur at the instant the cell is selected?
Okay. What about this. In your didSelectRowAtIndexPath start your spinner (via addSubview ...) and start loading your stuff from the server. If that's finished remove the spinner an push your new view controller onto the stack. Make sure the user can't touch any other cell during that time. By the way. From a users perspective I'd find it mor intuitive if the new controller is loaded immediately and displays some waiting message.
Or the other way around: The newGameViewController displays the spinner and starts loading the data from the server in a background thread. When the data is complete, remove the spinner and display the data. That way the user could even go back if she doesn't want to wait.
You do not need to add code before pushing newGameViewController.
Inside viewDidLoad of newGameViewController, write the code of displaying spinner. To get the updated UI, just insert a delay before calling a web API.
inside GameViewController.m
-(void) viewDidLoad
{
[self.view addSubview:LoadingView];
[self performSelector:#selector(callWebAPI) afterDelay:0.1];
}
-(void) callWebAPI
{
//Handle network activity here..
}
I have a UITableViewController class which when i call [self.tableView reloadData]; it gets stuck in a loop? Is there a way to break the loop?
The UITableViewController calls another class which then calls a method in the UITableViewController{
-(void)callToConfirm
{
[arrMain removeAllObjects];
[arrMain addObject:[searchText capitalizedString]];
[self.tableView reloadData];
NSLog(#"Symbol Exists!");
}
Post the backtrace of the loop. Without more information, it is impossible to say, but there are two scenarios that can lead to this:
You are calling reloadData while filling the table view. If you have any kind of lazy loading mechanism and that mechanism is triggered while loading the table view and it calls reloadData, then... boom.
Your data load is telling the table view that it is invalidated and needs to reload during the next pass through the run loop. Effectively looks like an infinite loop.
I'm using a UITableView control to show some data that can be edited by the user. To edit the details the user taps on an edit button which pushes a new view onto the stack. The user edits the data, taps a save button and the data is saved to a plist and the view popped off the stack. Even though the plist has been updated the UITableView still shows the old data. This can be corrected by adding a call to reloadData in the viewWillAppear method. However when the view is first loaded the data is displayed correctly, by adding the reload statement does this mean a double bind? If so, how can this be avoided?
I found the following code (here) which forces a refresh without explicitly calling reloadData:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
int orientation = [[UIDevice currentDevice] orientation];
if(orientation != UIDeviceOrientationUnknown)
[self willRotateToInterfaceOrientation:orientation duration:0];
}
Can anyone explain how/why this works?
The trick from your link is a dirty hack. Not only does it reload the data, but also forces the table to redraw. It tells your app that the device is getting a new orientation, so your table gets redrawn, along with other UI elements.
The standard way of refreshing a single row or a specific set of rows in your UITableView is calling its reloadRowsAtIndexPaths:withRowAnimation: method: doing so calls through to your data source to get data for only the row(s) that have been updated, preventing the full reload.
Do this:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//remove all objects from yourTableViewDataSourceArray
[yourTableViewDataSourceArray removeAllObjects];
//add new records from plist
yourTableViewDataSourceArray = plist request of data here
//reload table now
[yourtableView reloadData];
}
On the change of one view to another i want to load uitableview data after the viewdidappear of the new view occurs because if i load them in viewdidload it takes too much time to update the interface and the reason is the data loading. I want the interface to be loaded first so the user will be presented with the new interface and a "Loading..." label. Then data loading will occur and lastly the uitableview will appear.
Any help appreciated.
Load your data in the background as follows. Fill in the details with your own code to update your UI as you like and track status of the data being loaded. You can also look into other methods of executing background ops (look at the Concurrency Programming Guide) for more options and control.
- (void)viewDidLoad
{
[self performSelectorInBackground:#selector(loadData) withObject:nil];
}
- (void)loadData
{
#autoreleasepool {
// load the data
[self performSelectorOnMainThread:#selector(didLoadData) withObject:nil waitUntilDone:NO];
}
}
- (void)didLoadData
{
}