SF Symbols not loading into UIImageView - ios

I am creating an app for tracking health information, and I would like to use the two arrow images from SF Symbols. Unfortunately, no matter what I try, these symbols will not show up.
I have already tested the code with an image from the Assets folder, which seems to work with no problem in the UIImageViews I have created. It is only when I attempt to use UIImage(systemName: ) that I am having problems.
self.calendarView = UIView(frame: CGRect(x: 0, y: self.getCurrentY(), width: UIScreen.main.bounds.width, height: 60))
self.calendarView?.backgroundColor = .white
self.calendarView?.layer.borderColor = UIColor.black.cgColor
self.calendarView?.layer.borderWidth = 1
self.currentDate = UILabel(frame: CGRect(x: self.calendarView!.bounds.width / 4, y: self.calendarView!.bounds.height / 2 - 20, width: self.calendarView!.bounds.width / 2, height: 40))
self.currentDate!.text = "5/6/20"
self.currentDate!.textColor = .black
self.currentDate!.layer.borderColor = UIColor.black.cgColor
self.currentDate?.layer.borderWidth = 1
self.currentDate?.textAlignment = .center
self.calendarView?.addSubview(currentDate!)
//let testImage = UIImage(named: "logotest.jpg")!
let image1 = UIImage(systemName: "arrow.left")!.withTintColor(.blue)
let image2 = UIImage(systemName: "arrow.right")!.withTintColor(.blue)
self.leftArrow = UIImageView(image: image1)
self.rightArrow = UIImageView(image: image2)
self.leftArrow?.frame = CGRect(x: 10, y: 10, width: 40, height: 40)
self.rightArrow?.frame = CGRect(x: UIScreen.main.bounds.width - 50, y: 10, width: 40, height: 40)
self.leftArrow?.layer.borderWidth = 1
self.rightArrow?.layer.borderWidth = 1
self.calendarView!.addSubview(self.leftArrow!)
self.calendarView!.addSubview(self.rightArrow!)
self.contentView.addSubview(self.calendarView!)
What seems even stranger is that when I enter a breakpoint, the images actually show! I've attached a picture of this as well. Any help I can get with this is appreciated. Thanks!

Give your imageViews tint color will resolve the issue
leftArrow.tintColor = .blue
leftArrow.tintColor = .blue

1) You should be using constraints / auto-layout instead of explicit frames.
2) You should use if let and guard let to avoid all those ! and ?
Try it like this:
class ViewController: UIViewController {
var leftArrow: UIImageView!
var rightArrow: UIImageView!
var calendarView: UIView!
var currentDate: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//self.calendarView = UIView(frame: CGRect(x: 0, y: self.getCurrentY(), width: UIScreen.main.bounds.width, height: 60))
self.calendarView = UIView()
self.calendarView.backgroundColor = .white
self.calendarView.layer.borderColor = UIColor.black.cgColor
self.calendarView.layer.borderWidth = 1
//self.currentDate = UILabel(frame: CGRect(x: self.calendarView!.bounds.width / 4, y: self.calendarView!.bounds.height / 2 - 20, width: self.calendarView!.bounds.width / 2, height: 40))
self.currentDate = UILabel()
self.currentDate.text = "5/6/20"
self.currentDate.textColor = .black
self.currentDate.layer.borderColor = UIColor.black.cgColor
self.currentDate.layer.borderWidth = 1
self.currentDate.textAlignment = .center
//let testImage = UIImage(named: "logotest.jpg")!
guard let imgLeft = UIImage(systemName: "arrow.left"),
let imgRight = UIImage(systemName: "arrow.right") else {
fatalError("Could not create arrow images!")
}
let image1 = imgLeft.withTintColor(.blue)
let image2 = imgRight.withTintColor(.blue)
self.leftArrow = UIImageView(image: image1)
self.rightArrow = UIImageView(image: image2)
//self.leftArrow.frame = CGRect(x: 10, y: 10, width: 40, height: 40)
//self.rightArrow.frame = CGRect(x: UIScreen.main.bounds.width - 50, y: 10, width: 40, height: 40)
self.leftArrow.layer.borderWidth = 1
self.rightArrow.layer.borderWidth = 1
self.calendarView.addSubview(currentDate)
self.calendarView.addSubview(self.leftArrow)
self.calendarView.addSubview(self.rightArrow)
//self.contentView.addSubview(self.calendarView)
self.view.addSubview(self.calendarView)
[calendarView, currentDate, leftArrow, rightArrow].forEach {
$0?.translatesAutoresizingMaskIntoConstraints = false
}
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// calendarView to view (safe area) Top / Leading / Trailing
// Height: 60
calendarView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
calendarView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
calendarView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
calendarView.heightAnchor.constraint(equalToConstant: 60.0),
// currentDate label to calendarView centerX & centerY
// Width: 1/2 of calendarView width
// Height: 40
currentDate.centerXAnchor.constraint(equalTo: calendarView.centerXAnchor),
currentDate.centerYAnchor.constraint(equalTo: calendarView.centerYAnchor),
currentDate.heightAnchor.constraint(equalToConstant: 40.0),
currentDate.widthAnchor.constraint(equalTo: calendarView.widthAnchor, multiplier: 0.5),
// leftArrow to calendarView Leading: 10 Width: 40 Height: 40 centerY
leftArrow.leadingAnchor.constraint(equalTo: calendarView.leadingAnchor, constant: 10.0),
leftArrow.widthAnchor.constraint(equalToConstant: 40.0),
leftArrow.heightAnchor.constraint(equalToConstant: 40.0),
leftArrow.centerYAnchor.constraint(equalTo: calendarView.centerYAnchor),
// rightArrow to calendarView Trailing: -10 Width: 40 Height: 40 centerY
rightArrow.trailingAnchor.constraint(equalTo: calendarView.trailingAnchor, constant: -10.0),
rightArrow.widthAnchor.constraint(equalToConstant: 40.0),
rightArrow.heightAnchor.constraint(equalToConstant: 40.0),
rightArrow.centerYAnchor.constraint(equalTo: calendarView.centerYAnchor),
])
}
}
Output:
and, with auto-layout and constraints, it auto-sizes when needed - such as on device rotation:

Related

Programatically created UISwitch non-responsive

I have created a table that looks like what you see in the screenshot.
Here is the code:
lazy var contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)
lazy var scrollView : UIScrollView = {
let scrollView = UIScrollView(frame: view.bounds)
scrollView.backgroundColor = .white
scrollView.frame = self.view.bounds
scrollView.contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height * 200)
scrollView.autoresizingMask = UIView.AutoresizingMask.flexibleHeight
scrollView.bounces = true
return scrollView
}()
lazy var containerView : UIView = {
let view = UIView()
view.backgroundColor = .white
view.frame.size = contentSize
return view
}()
let weekStack = UIStackView()
weekStack.axis = .vertical
weekStack.distribution = .fillProportionally
weekStack.spacing = 2
containerView.addSubview(weekStack)
weekStack.translatesAutoresizingMaskIntoConstraints = false
weekStack.topAnchor.constraint(equalTo: restaurantImage.bottomAnchor, constant: 20).isActive = true
weekStack.leadingAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
weekStack.trailingAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
let arrayOfDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
for index in 0...arrayOfDays.count - 1 {
let dayStack = UIStackView()
weekStack.addArrangedSubview(dayStack)
dayStack.axis = .horizontal
dayStack.distribution = .fillEqually
dayStack.spacing = 4
let daySwitch = UISwitch(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
dayStack.addArrangedSubview(daySwitch)
let dayLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 20, height: 0))
dayLabel.text = arrayOfDays[index]
dayLabel.textAlignment = .center
dayLabel.font = UIFont(name: "NexaLight", size: 16)
dayStack.addArrangedSubview(dayLabel)
let startTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
startTextField.placeholder = "Open"
startTextField.textAlignment = .center
startTextField.delegate = self
startTextField.text = "9"
startTextField.font = UIFont(name: "NexaLight", size: 16)
dayStack.addArrangedSubview(startTextField)
startTextField.inputView = timePicker
startTextField.inputAccessoryView = toolbar
let closeTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
closeTextField.placeholder = "Close"
closeTextField.textAlignment = .center
closeTextField.text = "23"
closeTextField.font = UIFont(name: "NexaLight", size: 16)
closeTextField.delegate = self
dayStack.addArrangedSubview(closeTextField)
closeTextField.inputView = timePicker
closeTextField.inputAccessoryView = toolbar
}
The problem is that the last 2 switches are not responding as shown in the screenshot. I cannot turn them on. I also cannot interact with the last 2 rows of text fields where you see "9" and "23". This is from the simulator by the way.

How add vertical button list from top right corner programmatically in Swift 5

I need to add buttons from top right corner of the screen. I have added buttons. it is working fine in iPhone. But when I run to iPad it start on middle right corner of the screen. I have use below code..
let button1 = UIButton(frame: CGRect(x: view.frame.size.width - 56, y: view.frame.size.width - 220, width: 30, height: 30))
self.view.addSubview(button1)
let button12 = UIButton(frame: CGRect(x: view.frame.size.width - 56, y: view.frame.size.width - 150, width: 30, height: 30))
self.view.addSubview(button12)
How to add button from top right corner always both phone or iPad?
Change view.frame.size.width to a static value for y position. Because UIView position calculation starts from Top-Left corner.
let button1 = UIButton(frame: CGRect(x: view.frame.size.width - 56, y: 20, width: 30, height: 30))
self.view.addSubview(button1)
let button12 = UIButton(frame: CGRect(x: view.frame.size.width - 56, y: 60, width: 30, height: 30))
self.view.addSubview(button12)
If you want to add AutoLayoutConstraint try this
let button1 = UIButton()
button1.setTitle("Button 1", for: .normal)
button1.backgroundColor = .red
button1.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button1)
let button12 = UIButton()
button12.setTitle("Button 12", for: .normal)
button12.backgroundColor = .red
button12.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button12)
button1.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
button1.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
button1.heightAnchor.constraint(equalToConstant: 30).isActive = true
button1.widthAnchor.constraint(equalToConstant: 100).isActive = true
button12.topAnchor.constraint(equalTo: button1.bottomAnchor, constant: 20).isActive = true
button12.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
button12.heightAnchor.constraint(equalToConstant: 30).isActive = true
button12.widthAnchor.constraint(equalToConstant: 100).isActive = true
To know about translatesAutoresizingMaskIntoConstraints please check it - link
I would look into adding these directly to a storyboard. Possibly create these two buttons in a stackview. If you need go programmatically, the main issue with your above example is to use height instead of width for y:
let button1 = UIButton(frame: CGRect(x: self.view.frame.size.width - 56, y: self.view.frame.size.height - 220, width: 30, height: 30))
self.view.addSubview(button1)
let button12 = UIButton(frame: CGRect(x: self.view.frame.size.width - 56, y: self.view.frame.size.height - 150, width: 30, height: 30))
self.view.addSubview(button12)
You have to pin your buttons with constraints to that view like that:
NSLayoutConstraint.activate([
self.button1.topAnchor.constraint(equalTo: self.view.topAnchor, constant: *first button top margin*),
self.button1.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: *first button right margin*),
self.button2.topAnchor.constraint(equalTo: self.button1.bottomAnchor, constant: *second button top margin*),
self.button2.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: *second button right margin*)
])
Do not forget to add subviews like you did self.view.addSubview(button1)
You can also set constraints for width and height.
Apple docs: https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html#//apple_ref/doc/uid/TP40010853-CH16-SW1

NavigationItem.titleView is not getting the right size

I'm trying to set a custom view on a large navigationBar, but it insists on staying at 44px.
func setLargeNavBarForSection(_ section: String, subTitle: String, studyLogoName: String) -> Void {
if let navigationBar = self.navigationController?.navigationBar {
navigationBar.barTintColor = .cyan
navigationBar.shadowImage = UIImage()
let customView = UIView(frame: CGRect(x: 0, y: 0, width: navigationBar.frame.width, height: 96.0))
let sectionNameFrame = CGRect(x: 80, y : 23, width : 150, height : 41)
let subTitleFrame = CGRect(x: 80, y: 53, width: 200, height: 14)
let studyImageView = UIImageView(frame: CGRect(x: 20, y: 25, width: 45, height: 45))
studyImageView.image = UIImage(named: studyLogoName)?.imageWithInsets(insets: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
studyImageView.contentMode = .scaleAspectFit
studyImageView.backgroundColor = .white
studyImageView.layer.cornerRadius = 22
studyImageView.addShadow(radius: 3, opacity: 0.1, x: 1, y: 2)
let myStudiesButton = UIButton(frame: CGRect(x: navigationBar.frame.width-96, y: 36, width: 76, height: 26))
myStudiesButton.setImage(UIImage(named: "switchStudies"), for: .normal)
myStudiesButton.addTarget(self, action: Selector(("switchStudies")), for: .touchUpInside)
myStudiesButton.showsTouchWhenHighlighted = true
let sectionNameLabel = UILabel(frame: sectionNameFrame)
sectionNameLabel.text = section
sectionNameLabel.textAlignment = .left
sectionNameLabel.font = UIFont(name: "Montserrat-Bold", size: 18)
sectionNameLabel.textColor = .black
let subTitleLabel = UILabel(frame: subTitleFrame)
subTitleLabel.text = subTitle
subTitleLabel.textAlignment = .left
subTitleLabel.font = UIFont(name: "Montserrat-Medium", size: 11)
subTitleLabel.textColor = .blueGrey
// customView.addSubview(studyImageView)
// customView.addSubview(myStudiesButton)
// customView.addSubview(sectionNameLabel)
// customView.addSubview(subTitleLabel)
navigationItem.largeTitleDisplayMode = .always
customView.backgroundColor = .red
navigationItem.titleView = customView
}
}
navigationController?.navigationBar.prefersLargeTitles = true get called in the viewDidLoad on the ViewController.

Set background color for top safe area only in iOS 11

I'm new to Swift. I have set my top bar programmatically.It works fine for all versions except for iOS version 11.
I want to change the background color of the safe area in iPhone X. Presently I have just added the following code to hide the status bar.
override var prefersStatusBarHidden: Bool {
return true
}
I have created top bar using code:
//Top Bar
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)
Is there a way in which i can do it without using UINavigationBar or setting status bar.
Hi you can also try this one ,
need to add a view with same background which you set in your header view and add to container parent view .
please refer below code
//Top Bar
let safeAreaView = UIView(frame:CGrect(x: 0,y: 0, width: width, height: 40))
safeAreaView.backgroundColor = UIColor.white
self.view.addSubview(safeAreaView)
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)

Place label above each element in scrollview?

I'm populating my scrollview in a for loop and trying to place a UILabel on top of each inserted element. However, the label won't center horizontally for some reason even though I'm setting its centerXAnchor to be equal to each element's centerXAnchor. Here's a picture with the label and element's borders shown:
As seen, the label I'm inserting isn't being centered horizontally with each element in the scrollview for some reason. Here's my for loop where I populate the scrollview:
for i in 0..<petsDict.count {
let imageView = UIImageView()
imageView.image = petsDict[i]
imageView.contentMode = .scaleAspectFit
let xPos = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPos - CGFloat(20*i), y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
let label = UILabel(frame: CGRect(x: 0, y: -20, width: 200, height: 40))
label.text = "Joy"
label.textAlignment = .center
imageView.addSubview(label)
label.font = UIFont(name: "SFUIText-Regular", size: 20)!
label.sizeToFit()
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
label.centerXAnchor.constraint(equalTo: imageView.centerXAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: imageView.topAnchor).isActive = true
}
Can anybody help me understand why my x centering isn't working properly?
Try to remove label.sizeToFit(), this function resizes your labels.
for i in 0..<petsDict.count {
let imageView = UIImageView()
imageView.image = petsDict[i]
imageView.contentMode = .scaleAspectFit
let xPos = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPos - CGFloat(20*i), y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
let label = UILabel(frame: CGRect(x: 0, y: -20, width: self.mainScrollView.frame.width, height: 20))
label.text = "Joy"
label.textAlignment = .center
imageView.addSubview(label)
label.font = UIFont(name: "SFUIText-Regular", size: 20)!
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
label.centerXAnchor.constraint(equalTo: imageView.centerXAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: imageView.topAnchor).isActive = true
}
Try this code
Give width to label same as your imageview width and remove sizeToFit and anchor. You just need to add then textAlignment which you have already added.

Resources