Reloading UICollectionView causing flickering - objective-c

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

Related

iOS7 Keyboard Behavior with SearchBar/UITableView: Offset on secondary view appearances

Problem
I am having a rather big issue with the iOS7 keyboard appearance. I have a Searchbar on a UIViewController with TableView Delegation/Data Source setup (I am using the self.searchDisplayController delegates as well). I segue from this scene to a prototype tableview to show the results.
Here is the issue:
On first load I can see the keyboard being displayed when I tap into the text field of the UISearchBar. I can type and perform a search with the results being shown in the next scene.
I've added NSNotifications to view the keyboard properties in local methods keyboardWillShow and keyboardWasShown. I can see on the first scene appearance (after the view is completely loaded):
I segue to the result tableview at this point and when I navigate back and touch the text field, my keyboard shows up either fully or partially off-screen:
When I look at the keyboardWillShow notification at this point I can see that my keyboard values are incorrect:
I've researched and tried many possibilities including:
Added the following to my main view controller:
-(BOOL)canResignFirstResponder
{
return YES;
}
-(BOOL)canBecomeFirstResponder
{
return YES;
}
Configured the following in my view did load
self.searchDisplayController.searchBar.spellCheckingType = UITextSpellCheckingTypeNo;
self.searchDisplayController.searchBar.autocapitalizationType= UITextAutocapitalizationTypeNone;
self.searchDisplayController.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchDisplayController.searchBar.keyboardType = UIKeyboardTypeDefault;
Put in standard stubs for:
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
I've noticed that if I choose a Partial Curl as my segue mode, the keyboard remains accessible when I roll back to the main view controller (but then it was never fully off screen in that case). However if I move from the results tableview to a detail scene and then navigate back to the main view controller, the keyboard appears off-screen again.
Question
Is there a method I can use to intercept the misplaced keyboard so that it displays in the default location?
NB: Along these lines, I have created a NSDictionary property to hold the initial userInfo values with the correct keyboard placement. I am not sure how to reassign these values to get the keyboard to return to it's original placement.
BTW - This seems a bit of a hack to get the keyboard fixed due to a bug in IB, is there some other way that I can try to remedy the situation?
Thanks in advance for any feedback!
Solution
This was such an obscure issue that I'm sharing the solution to save the next person some effort. Like most programming issues, it turns out this one was self-inflicted. In my original iteration of this project I had turned off rotational support as I am learning auto-layout and I wanted to ease into the transition from Springs and Struts. Somehow between the start of the project and the code release I ended up with this bit of code in the Main Scenes' View Controller.
//BAD
- (NSUInteger) supportedInterfaceOrientations
{
return !UIInterfaceOrientationPortraitUpsideDown;
}
instead of returning a valid enumeration like...
//OK
- (NSUInteger) supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}

icarousel not displaying items

I've been working with iCarousel for about a week now, and I've had great success with outside testing. Now, I'm trying to put it into my app and it won't display the views. I was using UIViews to be displayed originally, which was working fine in my test programs, but due to sheer frustration im going as basic as possible and have literally just copied everythinng over from the examples. I connected the delegate and datasource, I called reloadData, ive done everything i could possibly find to fix this and it's not getting fixed. here's some code implementing the actual icarousel:
- (IBAction)coverflowPressed:(id)sender {
self.carousel = [[iCarouselExampleViewController alloc]
initWithNibName:#"iCarouselExampleViewController" bundle:nil];
[self presentViewController:self.carousel animated:YES completion:nil];
}
The rest of the code is basically copied from an example that works outside my app. As i mentioned, i DID connect the delegate and dataSource. It displays the background just fine, but it's like the carousel is empty; it has no items in it, and yes, there ARE items in it. any ideas for me?
EDIT
Maybe i connected the delegate and datasource wrong. could somebody maybe explain how to do that from an app thats already halfway through production?
Breakpoints prove that it's never reaching carousel-specific functions, like viewForItemAtIndex or even awakeFromNib. viewDidLoad is called, so i set the delegate and datasource in there. Originally they were set in the nib but i changed it to programmatically. anyways heres my viewdidload method:
- (void)viewDidLoad {
[super viewDidLoad];
self.carousel.delegate = self;
self.carousel.dataSource = self;
//configure carousel
_carousel.type = iCarouselTypeCoverFlow2;
}
it reaches the end of this function but it never goes any farther with it...

UITableView Refresh Query

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

xcode page-based application

I am trying to create an app based on the page-based application template in xcode 4, that has a title page, table of contents page, and content pages, all formatted differently. I am new to ios programming, completed the 3 apple tutorials and read a lot of documentation but this is basically my first non-tutorial app.
I'd really appreciate a code example or instructions that shows how to do this properly. This particular template does not seem to have many examples out there.
specifically:
I created a new xcode project and chose the page-based application
template (i'm not including the source code here because it should
be easy to generate for anyone with xcode 4)
The template creates an AppDelegate, a RootViewController, a DataViewController and a ModelController
For now, I don't care about showing dynamic data. I want the first page to show a view with a label that says "Title" and the
second page and after to show a text area filled with lorem ipsum.
I have created a TitlePageView and ChapterView in the storyboard and
corresponding ViewController files, but do not know how to tie them
to the DataViewController so that they display.
Yeah, I'm not sure how to do it using storyboard, but if you want a simple cut-and-paste solution using nibs, I posted one here: https://stackoverflow.com/a/9687639/542400
This is how I ended up putting different views on each page.
Create the views for each page in the storyboard, and leave them without a segue or connection to the main page. (you get yellow warning for this)
Set the 'identifier' property for each new view to some unique string, e.g. "titlePage"
Create an outlet for the big white part of the default page view called "contentArea" in the DataViewController
Update the DataViewController class viewWillAppear method to create your page views and add them as sub-views to the contentArea:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (_contentArea.subviews.count == 0)
{
UIView *pageSubView;
UIViewController *pageSubViewController;
pageSubViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"titlePage"];
[self addChildViewController: pageSubViewController];
[pageSubViewController didMoveToParentViewController:self];
pageSubView = pageSubViewController.view;
[_contentArea addSubview:pageSubView];
CGRect pageViewRect = _contentArea.bounds;
pageSubView.frame = pageViewRect;
}
}
here is the code snippet for creating a page
pageInfoLabel.text = [NSString stringWithFormat:#"Some really useless information on page %d", pageNumber + 1];

Load uitableview data after viewdidappear occurs?

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
{
}