Xcode shows labels, buttons, navigation bar & images as pixelated - ios

As you can see in this screenshot:
The Navigation bar, buttons and the speaker image are pixeled.
I migth think that it has a connection to the View Hierarchy - this View is on top of the main View (The main view label and buttons looks good and not pixeled), written in Swift:
var navUser = UIViewController()
class ViewControllerMenu: UIViewController {
navUser = storyboard!.instantiateViewController(withIdentifier: "navUser")
addChildViewController(navUser)
navUser.view.frame = view.frame
view.addSubview(navUser.view)
navUser.didMove(toParentViewController: self)
navUser.view.alpha = 0
navUser.view.layer.shadowColor = UIColor.black.cgColor
navUser.view.layer.shadowOpacity = 1
navUser.view.layer.shadowOffset = CGSize.zero
navUser.view.layer.shadowRadius = 10
navUser.view.layer.shadowPath = UIBezierPath(rect: navUser.view.bounds).cgPath
navUser.view.layer.shouldRasterize = true
}
I'm adding the View Hierarchy of this view:
This happens in all the Xcode iPhone simulators and in my personal iPhone 7.

This seems to be an odd usage of .shouldRasterize ... that is normally used when re-displaying a complex view / layer multiple times (such as game animation).
Removing that line - navUser.view.layer.shouldRasterize = true - should fix the problem.

Related

Bottom corners arent round

I'm having an issue with some container views.
The main view has 2-container views. One of them is just a container view, straight up from the drop-off menu with nothing more than it's child VC being modified via Storyboard. (the embedded one).
The second Container View has a Scroll-view inside and a second view inside the container view with a custom size. (I saw a tutorial on youtube).
Now on my viewdidload on the HomeVC I call the following code:
func setupViews() {
containerTop.layer.cornerRadius = 15
containerTop.clipToBounds = true
containerBot.layer.cornerRadius = 15
containerBot.clipToBounds = true
}
The above code results in THIS RESULTS. As you can see all but 2 corners are rounded (the bottom 2 corners of the top view). Why is this happening and how can I fix this?
I'm not 100% sure about why you are having this odd behaviour, I also experienced something similar and fixed like following: (Your project should be supporting iOS11++ in order for this solution to work:
func setupViews() {
containerTop.layer.cornerRadius = 15
containerTop.clipToBounds = true
containerBot.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
containerBot.layer.cornerRadius = 15
containerBot.clipToBounds = true
}
Thank you for the suggestion. Unfortunately it didnt work.
I was able to fix it by doing the following:
On the storyboard tree On the ViewController there is a View on the element tree. I linked that as an outlet in my code and made it's corners round. Basically I called the round corners twice:
- Home View controller had:
func setupViews() {
containerTop.layer.cornerRadius = 15
containerTop.clipToBounds = true
containerBot.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
containerBot.layer.cornerRadius = 15
containerBot.clipToBounds = true
}
And then the ContainerTopViewController had inside a View (per storyboard) and the code is:
class ContainerTopViewController: UIViewController {
<LINKED THROUGH STORYBOARD> myView: UIViewController
func loadView() {
myView.layer.cornerRadius = 15
myView.layer.clipToBounds = true
}
}

Adding and removing UIStackViews messing up my UIScrollView

Whenever I use the pickerview to switch views from Auto Rent to Schedule Rent it works perfectly. It is when I switch from Schedule Rent to Auto Rent that this black bar appears. I have attached the hierarchy of my content view. I thought it had to do with previous constraints added, so I remove a StackView whenever one view is chosen. For example, if Auto Rent is chosen, then I remove the StackView where the Schedule View is in:
//Holds Temp Stackviews
var stackViewHolder1: UIView?
var stackViewHolder2: UIView?
override func viewDidLoad() {
super.viewDidLoad()
stackViewHolder1 = stackViewMain.arrangedSubviews[0]
stackViewHolder2 = stackViewMain.arrangedSubviews[1]
}
if txtRentType.text == "Auto Rent" {
let tempView = stackViewHolder1
let tempView1 = stackViewHolder2
tempView!.isHidden = true
stackViewMain.removeArrangedSubview(tempView!)
if(tempView1!.isHidden == true){
tempView1!.isHidden = false
stackViewMain.addArrangedSubview(tempView1!)
}
else{
let tempView = stackViewHolder1
let tempView1 = stackViewHolder2
tempView1!.isHidden = true
stackViewMain.removeArrangedSubview(tempView1!)
if(tempView!.isHidden == true){
tempView!.isHidden = false
stackViewMain.addArrangedSubview(tempView!)
}
}
I have tried deleting one view and toggling only one view has being hidden and that removes the black bar issue. There is no constraint with the stackViews and Content View.
EDIT:
The screen highlighted is the scrollView. The one after is the contentView. UIWindow goes black in the back.
My Title Bar at the top ends up in the middle somehow.
You can try to modify your stack distribution property
stack.distribution = .equalCentering
After you won't need to use this:
.removeArrangedSubview()
.addArrangedSubview()
When you hide some view, the other view take all space of your stack, you don't need to update your constraints. You can try it on interface builder to see how it works.
are you pinning your scrollview and the content view to the bottom with constraints?
If the content view is a stack view you can pin it to the bottom as well with layout constraints and play with the content distribution.
You don't need to use remove/Add arranged subviews.
when hiding a view in a stackView its automatically removed.
so i think you can just hide or show the stackViewMain.subviews[0] o stackViewMain.subviews[1]
i'm with objc maybe i do a mistake but it would be something like this :
if txtRentType.text == "Auto Rent" {
stackViewMain.arrangedSubviews[0].isHidden = true;
stackViewMain.arrangedSubviews[1].isHidden = false;
}else{
stackViewMain.arrangedSubviews[1].isHidden = true;
stackViewMain.arrangedSubviews[0].isHidden = false;
}

Shrink UIView from top

I have a uiview that is overlaying and blocking interaction with my view on top of the superview. I've tried bringing the blocked view to the front but that doesn't work either.
Here's the code for the blocking view:
self.gesstureView = UIView(frame: screenBounds)
if let gestureView = self.gesstureView, let controlDockView = self.controlDockView, let controlTopView = self.controlTopView {
gestureView.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
gestureView.frame.size.height -= controlDockView.frame.height
gestureView.contentMode = .center
gestureView.backgroundColor = UIColor.red
self.view.addSubview(gestureView)
Heres the code for the view that's blocked:
let topHeight = screenBounds.height * 0.15
self.controlTopView = UIView(frame: CGRect(x: 0, y: 0, width: screenBounds.width, height: topHeight))
if let controlTopView = self.controlTopView {
controlTopView.backgroundColor = UIColor.clear
controlTopView.autoresizingMask = [.flexibleTopMargin]
controlTopView.addBlurEffect()
self.view.addSubview(controlTopView)
// does not work view is still hidden
self.view.bringSubview(toFront: controlTopView)
Thanks for the sample code!
The problem is that you add your gestureView to the view hierarchy after you brought controlTopView to front. So controlTopView will actually be the second view this is why it is not visible.
To solve the problem either add controlTopView lastly or bring it to the front after you've added everything.
view.addSubview(previewView)
view.addSubview(controlDockView)
view.addSubview(gestureView)
view.addSubview(controlTopView)
Just in case -- have you checked if your controlTopView is not visible simply because it has nothing visible to draw? In your code snippet, the controlTopView only has a transparent background color and a blur effect (which wouldn't do anything to the solid red behind it).
The best way to really see whats going on is to use the UI debugger in Xcode. It will show you what is obscuring what. Also, it is very likely that the UIViews are being drawn in an order you are not anticipating.
You should resize and select the hidden view....if its actually there.

LeftBarButtonItem with UISearchBar is not visible on iOS 11

The title is pretty self explanatory, on iOS 10.3 using a UIBarButtonItem with a custom view (in this case UIStackView) assigned to a LeftBarButtonItem of a NavigationBar is not visible on iOS 11. I haven't figure out why it is not showed but when I type something with the keyboard my logic of the TextChanged event works! So the UISearchView is there but it is not visible:
Here is some code (It is coded with C# but it is using Objective C methods.):
var width = NavigationController.NavigationBar.Frame.Width;
var height = NavigationController.NavigationBar.Frame.Height;
_searchBarContainer = new UIStackView(new CGRect(0, 0, width * 0.75, height))
{
Alignment = UIStackViewAlignment.Center,
Axis = UILayoutConstraintAxis.Horizontal,
Spacing = 3
};
_uiSearchBar = new UISearchBar
{
BackgroundColor = UIColor.Clear,
BarTintColor = UIColor.Clear,
BackgroundImage = new UIImage(),
Placeholder = Strings.Search
};
_uiSearchBar.SizeToFit();
if (_iOS11)
{
_uiSearchBar.HeightAnchor.ConstraintEqualTo(44).Active = true;
}
_searchbarButtonItem = new UIBarButtonItem(_searchBarContainer);
NavigationItem.SetLeftBarButtonItem(_searchbarButtonItem, true);
ParentViewController.NavigationItem.LeftBarButtonItem = NavigationItem.LeftBarButtonItem;
Using the same code on iOS 10 this works.
Please try out setting up constraints to size properly your _searchBarContainer before setting it as the left bar button item. From iOS11 navigations bars use auto layout. Make sure you only add the constraints if iOS 11 is present, I was having problems in iOS 9 navigation bars otherwise.
Also checkout this thread in the Dev forum where it's explained how the bar items are wrapped inside stack views, maybe also helps with your particular issue.

iOS 11 breaks row selection

I've recently tested my app in iOS 11 and for some reason I'm not able to select one of the first 12 rows in a dynamically populated table view. The didSelectRow isn't even triggered for these rows. The other rows work fine, but even when scrolling down and back up (the cells should have been re-used again by then) the first 12 rows don't work.
Even on a static table view all cells that appear on screen when switching to that view controller will not respond, neither will controls inside them, even when they are in different sections. Cells that are out of screen initially again work fine.
I'll be trying to test this in an app with boilerplate code, but is this a known bug? I couldn't find anything online about it.
I've tested this after updating the devices to iOS 11, then again from Xcode 9 beta 6 without changes to the code, and again after migrating to Swift 4. Same behaviour inside the simulator. Up to iOS 10 everything is fine, only with iOS 11 the problem occurs.
This will break my app for users in two weeks, I need to fix it, so any help or advice very much appreciated!
UPDATE: As Paulw11 suggested, there is indeed another view blocking the rows. This was notable as row 12 could only be selected in the lower part of the cell, but not in the upper part.
The cause for this issue is the following code:
extension UIViewController {
func setBackgroundImage(forTableView tableView: UITableView) {
let bgImage = UIImage(named: "Background Image.png")
let bgImageView = UIImageView(image: bgImage)
tableView.backgroundView = bgImageView
let rect = bgImageView.bounds
let effect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurView = UIVisualEffectView(effect: effect)
let height: CGFloat
switch screenSize.height {
case 480, 568: height = 455
case 736: height = 623
default: height = 554
}
blurView.frame = CGRect(x: 0, y: 0, width: rect.width, height: height)
let container = UIView(frame: rect)
bgImageView.addSubview(blurView)
let bgOverlay = UIImage(named: "Background Overlay.png")
let bgOverlayImageView = UIImageView(image: bgOverlay)
bgOverlayImageView.alpha = 0.15
bgImageView.addSubview(bgOverlayImageView)
self.view.insertSubview(container, at: 1)
}
}
Somehow since iOS 11 this background image seems to be rendered in front of the cells. Not inserting the container view into the table view's view will solve the issue. I've tried setting the zPosition of the container's layer but it does not help. How can I move the background image behind the cells again.
It's weird that this behaviour would change from iOS 10 to 11...
UPDATE 2: Inserting the container at index -1 fixes the issue:
self.view.insertSubview(container, at: -1)
I don't get why this works, though, shouldn't this index be out of range?
UPDATE 3: As Paulw11 pointed out below, the container is completely useless, it was left over from testing and removing it fixes the issue.
The container view seems to be appearing in front of the other views and preventing touches from making it through to the table view.
As an aside, I would see if you can refactor this to use constraints; It always worries me when you see hard-coded screen sizes, as that may break when new devices are released.

Resources