I came here because I have a pretty weird problem with my UICollectionView.
Imgur album with all the screens I would like to share: http://imgur.com/a/v3sox
First of all, here's what my app looks like with no problem: Image 2 of the album.
Notice the refresh button in the top-right corner, this is the one which is giving me problems.
When I scroll down the UICollectionView very fast, and press "refresh" while the Collection View is still scrolling, I've got "cell leftovers" which do not belong to anybody and just stay on the screen.
(ex: Image 1 of the album)
I don't understand what's happening because in my refresh method I have:
- (void)refreshData
{
//A bunch of code before I reset the data
dispatch_async(dispatch_get_main_queue(), ^{
//Reset data
currentProjects = nil;
[self.projectsCollectionView reloadData];
//Some other stuff concerning the little "Chargement..." view
};
}
The cells then proceed to stay on my screen on every folder, so if I choose another folder, I'll get Image 3 of the album (notice the labels for the last 4 cells, they are mixed up, because the previous cells are still on the screen when they shouldn't be.)
Has anybody got an idea on what could possibly cause this? Thanks a lot for your time
P.S: sorry i put all the screens in an album, couldn't post more than 2 links so I had to improvise
Just had the same problem too. I solved it by modifying the UICollectionViewCell.
(note: my code is c# using MonoTouch).
before the cell was creating the objects each time. ie.
textView = new UITextField()
{
BackgroundColor = UIColor.Clear,
TextColor = UIColor.LightGray,
Text = Title
};
to fix it, check for the object, and update it accordingly.
if (textView == null)
{
textView = new UITextField()
{
BackgroundColor = UIColor.Clear,
TextColor = UIColor.LightGray,
Text = Title
};
}
else
textView.Text = Title;
now when reload data is called on the CollectionView, it reloads correctly.
I have had this similar issue once. The problem is my custom cell creates subview again and again.
From my guess, you should change the value of the label instead re-create it after dequeue.
Related
I have a problem with transparency in my Views, especially with UITableView.
Just to make sure. I already have 3 years of experience with swift and this is the first time, I am getting this problem.
So in apple's docs it says the following:
backgroundColor
The view's background color.
Changes to this property can be animated. The default value is nil, which results in a transparent background color."
But when applying clear color to backgroundColor or tableView.backgroundColor = UIColor.clear, the background is still appearing white.
Is this a bug or a feature?
EDIT:
The tableView isn't the problem anymore. It is the cell within the tableView.
Already tried solutions are clearing the background color of all subviews. Nothing changed.
EDIT 29.09.17
Ok, I debugged my application and got this:
UICachedDeviceWhiteColor and cachedColor.
A google searching also didn't help.
Edit 29.09.2017 Later that day ...
The problem occurs, when updating from swift 3 to swift 4.
I made a new project with swift 4, but it actually works fine.
Because it is a problem I have to solve. I will try some things and update this post from time to time.
In UITableViewCell and UICollectionViewCell there is a property view called contentView.
A common mistake is to manipulate the cell directly. Instead try to manipulate the cells content view:
Obj-c
UITableViewCell *cell = ....// get the cell
cell.backgroundColor = ... // BAD !
cell.contentView.backgroundColor = [UIColor redColor] // this is the correct way.
Swift
let cell = ...
cell.contentView.backgroundColor = UIColor.red // make sure its the contentView
also a couple small nuances with colors and opacity:
If you want only the background to have opacity (i.e. less than 100%) , make sure you are not changing the view's opacity (i.e. view.alpha = 0.5 BAD) - change the color's opacity value instead:
i.e.
cell.contentView.backgroundColor = [UIColor colorWithRed:... green:... blue:... alpha:0.5];
Another useful trick is to pause the application and press the "visual debug" button.
Search for your view and check it's attributes in the inspector
Found the problem:
When instantiating a variable which holds the view before displaying it, the background color of this view is white. The debugger calls this UICachedDeviceWhiteColor.
Why would you do that?
If you instantiate the view before it is displayed, you can switch with a menu between different views very fast with "bringSubview(toFront: ...).
How to fix:
To fix this you have to instantiate the view every time you want to show it.
Hope I could help some lost souls with this answer and Apple is going to fix this bug.
Verify that the view behind it is not white, then set the current view's (the one with the transparent background) modalPresentationStyle to overCurrentContext. This will allow views behind to show through the UIColor.clear background color.
If you are setting
tableView.backgroundColor = .red
and if it's an empty TableView then the Red will be visible. I give a headerView and FooterView also to visualise.
Now TableView Contents some data, so to reflect the color you need to set background color to cell.
class UserCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = .yellow
}
....
}
You can check out the original project here.
I am making a Calendar app and I am showing the events from the Calendar in a UITableView.
I am using a tableFooterView to hide separator lines in a UITableView when the table is empty. I do this with the following code:
self.tableView.tableFooterView = [[UIView alloc] init];
UILabel *footerTableViewLabel = [[UILabel alloc] init];
footerTableViewLabel.text = #"No items.";
[self.tableView.tableFooterView addSubview:footerTableViewLabel];
If there are elements in the table, I hide this view, and if not I show it. This works fine if the calendar is initially empty. However, if I delete an event from Calendar.app while my app is still running in the background, when I go back to the app, all I see is a bunch of empty cells and separator, and no label saying "No items".
Any ideas?
EDIT: I show/hide the footer view using:
self.tableView.tableFooterView.hidden = NO/YES;
As far as events are considered, I do not offer the possibility to delete them directly from my app, I just detect when they are deleted from Calendar.app. Unfortunately, I cannot show the code doing this detection since it is part of a private library, however, this works fine, i.e. I jump to right parts of code when the event is deleted.
You can try this un your code to hide separators: self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
Use self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; to hide the separator lines. If you want the active tableview cells to have separators, you can always add a border to the bottom of each cell manually using a function like this:
- (void)addBottomBorderWithColor:(UIColor *)color andHeight:(CGFloat) borderHeight
{
CALayer *borderBottom = [CALayer layer];
borderBottom.backgroundColor = color.CGColor;
borderBottom.frame = CGRectMake(0, self.frame.size.height, self.frame.size.width, borderHeight);
[self.layer addSublayer:borderBottom];
}
** EDIT**
If you want to add a view that indicates 'no data', try adding this as a view underneath the tableview, then just set the tableview to hidden if there is no data present.
Hope this helps
So, I finally managed to figure this out. There were to issues:
For some reason (maybe when I do [self.tableView reloadData]), self.tableView.tableFooterView would become nil and that's why I could see empty cells. Reassigning the view to it fixed this issue.
I had to update the view constraints for the footer view and the label it contains.
I'm preparing a UITableView with a custom prototype cell having a UISwitch widget on the right side, and I'd like to let my users be able to delete rows.
Everything is fine with that, except the fact that when the delete button shows up it overlaps to the UISwitch, this way:
Is it possible to have the UISwitch shifting left when the delete button appears?
Epilogue
I've decided for brevity to not shift my UISwitch position when "delete" button appears, but to make it disappear, bringing it back when the "delete" button is gone.
So, according to #geo suggestion (thank you), I've managed it out (quite simply) this way:
In my UITableViewCell' subclass .m file:
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if (state & UITableViewCellStateShowingDeleteConfirmationMask) {
activationSwitch.hidden = YES;
}
else {
activationSwitch.hidden = NO;
}
}
I hit a very similar problem and fixed it. You need the right autoresizing mask (assuming not doing auto layout here) for your UI elements in your custom tableview cell in Interface Builder.
In my case, I needed to add the Left constraint (see that little autoresizing picture/animation in the Size Inspector, View section) for each of my UI elements.
Add a Left "bar", and you should be good.
Override the Methode
-(void)willTransitionToState:(UITableViewCellStateMask)state
-> UITableViewCellStateShowingDeleteConfirmationMask
of your custom Cell and do there your customizing :)
In short, I need to restore the default backgroundView for a UITableViewStyleGrouped cell.
cell.backgroundView = ??;
The long story:
I have a grouped tableview with some cells. For every cell the user needs to select some value or do some input. After that he can proceed to the next ViewController by touching a "next" button.
Anyway, to indicate to the user that he missed something, I display a nice red border around the cell with the wrong/missing user input. I do that by setting the backgroudView of the cell with a custom image like this:
cell.backgroundView = myErrorIndicatingImageView;
The cell now looks like this (screenshot, ignore the stars and label)
So far so good, this works like a charm. But after the user corrects the input I want to remove my red border background image and just show the original background again. The original background looks like this (screenshot):
And this seems to be a problem.
I tried several things
// try by setting the background to nil
cell.backgroundView = nil;
this removes the background completely and I'm lost with a cell without background.
// try it with addSubview and later remove the subview again
[cell.backgroundView addSubview:myErrorIndicatingImageView];
this does nothing. The myErrorIndicatingImageView is not visible. Even a [cell.backgroundView bringSubviewToFront:myErrorIndicatingImageView] does not help.
Right now the only solution I have is to create a new UITableViewCell for every single call to cellForRowAtIndexPath. This works but is just bad code and ignores completely the technique to reuse cells.
There must be a simpler solution...something like
cell.backgroundView = [self.tableView getDefaultBackgroundView];
what about trying this:
cell.backgroundView = [[UIView alloc] initWithFrame:cell.backgroundView.frame];
Or you can make the background view as a UIImageView and set 2 images in problem and fixed
Assuming you are doing this with a custom table cell class, save the original backgroundView in some ivar, then apply the new background. When you want to reset the background, set the backgroundView back to the original, saved background view.
I am working with alertViews to load to them different objects, such as textFields and others.
With textFields there is no problem. I have successfully added a UIPickerView as a subview of my alertView and I had resized the alertView.frame to hold the pickerView properly, but then the title and the button in the alertView are not centered.
I tried with many of the options [alertView …function…] but none seems to work with this issue. This looks bad in a custom sized alertView. Any suggestions?
Thanks folks!
to solve the Title issue, I got inspiration from this post: Custom AlertView With Background
First of all, when the App presents the alertView, I called a NSLog to get:
the pickerView's (my subview) width
the _titleLabel's width
the _titleLabel's starting position (MinX and MinY)
then I resized the _titleLabel frame and that was all!
textAlignment is Center by default so all I had to do was resize the label frame. other possible method is to use
[theTitle CGAffineTransformMakeTranslation(newXValue, 0];
Y value is 0 because I didn't want it to move vertically. But the described method is cleaner to me.
so what I added to the method that creates&presents my alertView was this:
NOTE: this code HAS to go BEFORE the addition of any additional view to the alertView!
//... alertView creation and display
//create a title object to edit titleLable properties
UILabel *theTitle = [pickers valueForKey:#"_titleLabel"];
// set frame for titleLabel to begin where it currently begins in both X and Y, set its width to the width of th e picker +/- the difference in X in case they don't have the same MinX value, and set the height it already has
theTitle.frame = CGRectMake(CGRectGetMinX(theTitle.frame), CGRectGetMinY(theTitle.frame), CGRectGetWidth(pkPais.frame)+6, CGRectGetHeight(theTitle.frame));
//...add subviews and set its frames (in my case, a pickerView)
as for the button, i found in the UIAlertView.h file that buttons cannot be customized...so if someone has any tip on this issue, any help will be appreciated.
hope this helps someone else!
UPDATE: As I mentioned, Apple said buttons in alertViews cannot be customized, so there are two alternatives: create a custom button and add it as subview or have no button at all. In my case I did so, and called [myAlertView dismissWithClickedButtonIndex:-1 animated:YES] in the didSelectRow...inComponent part of the pickerView code.
This worked for me just fine, but I am open to new ideas!!
See ya!