Unable to set the custom header view in UITableView - ios

I am trying to make the custom header for the UITableView but it is showing the "fatal error: unexpectedly found nil while unwrapping an Optional value". The code is like this:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 40))
self.headerImage?.frame = CGRect(x: (headerImage?.frame.size.width)! + 20, y: 20, width: 10, height: 10)
headerLbl?.frame = CGRect(x: (headerImage?.frame.size.width)! + 20, y: 20, width: 10, height: 10)
arrowImage?.isHidden = true
arrowImage?.frame = CGRect(x: menuTableView.frame.size.width - 30, y: 20, width: 10, height: 10)
if selectedIndex == section {
arrowImage?.image = UIImage(named: "down arrow")
} else {
arrowImage?.image = UIImage(named: "side_arrow")
}
let headerClick = UIButton(type: .custom)
headerClick.addTarget(self, action: #selector(self.headerAction), for: .touchUpInside)
headerClick.frame = CGRect(x: 0, y: 0, width: menuTableView.frame.size.width, height: 40)
headerClick.tag = section
headerClick.backgroundColor = UIColor.clear
headerView.addSubview(headerImage!)
headerView.addSubview(headerLbl!)
headerView.addSubview(arrowImage!)
headerView.addSubview(headerClick)
return headerView
}
func headerAction(_ sender: UIButton) {
if selectedIndex == sender.tag {
selectedIndex = -1
}
else {
selectedIndex = Int(sender.tag)
}
menuTableView.reloadData()
}
}
But the error which is getting from this code is as shown in the screenshot below:
Why i am getting the error like this. Any ideas on it?

Related

Set section header padding of tableview for second header in old iOS

I'm setting header padding for my tableview in iOS older than 15 explicitly. This works for the top first header (section 1 of tableview), but doesn't work for second header (section 2 of tableview). How could I set it for the second also?
Is there something like tableView.tableHeaderView[2] or tableView.tableHeaderView.second ?
In code its the place with commented-out places.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if tableView.tag == 2 {
if section == 0 {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
let view = UIView()
let imageView = UIImageView(image: UIImage(named: "Logo_face"))
if #unavailable(iOS 15.0) {
imageView.frame = CGRect(x: 10, y: 20, width: 25, height: 25)
} else {
imageView.frame = CGRect(x: 10, y: 0, width: 25, height: 25)
}
view.addSubview(imageView)
let label = UILabel()
label.text = "店舗"
label.frame = CGRect(x: 40, y: 0, width: 200, height: 25)
view.addSubview(label)
if #unavailable(iOS 15.0) { //setting here; works
let padding: CGFloat = 20
view.frame = CGRect(x: view.frame.origin.x - padding,
y: view.frame.origin.y - padding,
width: view.frame.width + 2 * padding,
height: view.frame.height + 2 * padding)
tableView.tableHeaderView = view // this is good
label.frame = CGRect(x: 40, y: 20, width: 200, height: 25)
}
return view
}
} else {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
let view = UIView()
let imageView = UIImageView(image: UIImage(named: "pinIconForSearch"))
if #unavailable(iOS 15.0) {
imageView.frame = CGRect(x: 10, y: 20, width: 25, height: 25)
} else {
imageView.frame = CGRect(x: 10, y: 0, width: 25, height: 25)
}
view.addSubview(imageView)
let label = UILabel()
label.text = "検索候補"
label.frame = CGRect(x: 40, y: 0, width: 200, height: 25)
view.addSubview(label)
if #unavailable(iOS 15.0) { //setting here doesnt work
let padding: CGFloat = 20
view.frame = CGRect(x: view.frame.origin.x - padding,
y: view.frame.origin.y - padding,
width: view.frame.width + 2 * padding,
height: view.frame.height + 2 * padding)
tableView.tableHeaderView = view // this is not good
label.frame = CGRect(x: 40, y: 20, width: 200, height: 25)
}
return view
}
}
}
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0.0
} else {}
return nil
}

Swift button only showing in dark mode

I am adding a button in a tableview section header, and it currently only shows while my phone is in dark mode, I have no idea what the issue might be. All other elements in the header show in both light and dark mode.
headerHeight is a static 200 pixels
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: headerHeight))
let imageButton = UIButton(frame: CGRect(x: view.frame.width / 2 - 50, y: 10, width: 100, height: 100))
imageButton.setImage(UIImage(systemName: "person.crop.circle"), for: .normal)
view.addSubview(imageButton)
let nameButton = UIButton(frame: CGRect(x: 0, y: 110, width: tableView.frame.width, height: 40))
nameButton.tintColor = .label
nameButton.titleLabel?.textColor = .label
nameButton.setTitle("Set Name", for: .normal)
nameButton.titleLabel?.textAlignment = .center
view.addSubview(nameButton)
let accountsLabel = UILabel(frame: CGRect(x: 10, y: 175, width: 80, height: 20))
accountsLabel.text = "Accounts"
accountsLabel.font = UIFont(name: "Helvetica Neue", size: 15)
view.addSubview(accountsLabel)
return view
}
The problem is this line:
nameButton.titleLabel?.textColor = .label
That is not how you set a button's title color. Change it to:
nameButton.setTitleColor(.label, for: .normal)

Add UIButton and UIImage in TableView Section header

I can't figure out what is wrong in this code. i want to display button and image in tableview section header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
let image = UIImageView()
image.frame = CGRect(x: view.frame.width - 10 , y: 0, width: 20, height: 20)
image.image = UIImage.init(named: "triangle.png")
let button = UIButton(type: .system)
button.frame = CGRect(x: view.frame.origin.x, y: view.frame.origin.y, width: view.frame.width - 30, height: view.frame.height)
button.setTitle("Open", for: .normal)
button.backgroundColor = .yellow
button.addTarget(self, action: #selector(buttonclick), for: .touchUpInside)
view.addSubview(image)
view.addSubview(button)
return view
}
You shouldn't set imageView and button frame by view frame. Because when viewForHeaderInSection function is being called view frame will be 0.
Instead of view you can use tableview
image.frame = CGRect(x: tableView.frame.width - 20 , y: 0, width: 20, height: 20)
button.frame = CGRect(x: 0, y: 0, width: tableView.frame.width - 30, height: 50)
It is recommended to use autolayout instead of setting frame.
Add below code just after initialising view :
view.frame = CGRect(x: 0 , y: 0, width: tableView.frame.width, height: heightForHeaderInSection)
you forgot to set the view's frame.

Moving UIImage Up and Down with Animation in Swift

I have just recently started with Xcode and Swift and I am trying to get my image to move up and down and have it switch directions when the user taps the screen. My image just will not move at all and the app will either crash or just freeze.
import UIKit
import SpriteKit
import Darwin
let startButton = UIButton(frame: CGRect(x: 200, y: 100, width: 100, height: 50))
let screenSize = UIScreen.main.bounds
let gameButton = UIButton(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
var dot: UIImage = UIImage(named: "dot")!
var dotPic = UIImageView(image: dot)
public var goingUp = true
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
startButton.addTarget(self, action: #selector(startButtonAction), for: .touchUpInside)
startButton.setImage(UIImage.init(named: "startButton"), for: .normal)
self.view.addSubview(startButton)
}
func startButtonAction(sender: UIButton!) {
print("button clicked")
startButton.isEnabled = false
startButton.setImage(UIImage.init(named: "nothing"), for: .normal)
self.view.backgroundColor = .gray
dotPic.frame = CGRect(x: 50, y: 300, width: 20, height: 20)
self.view.addSubview(dotPic)
self.view.addSubview(gameButton)
playGame()
}
func playGame(){
gameButton.addTarget(self, action: #selector(gameButtonAction), for: .touchUpInside)
gameButton.setImage(UIImage.init(named: "nothing"), for: .normal)
}
func gameButtonAction(sender: UIButton!) {
goingUp = !goingUp
print(goingUp)
print("clicked up/down")
func rep(){
repeat{
dotPic.frame = CGRect(x: 50, y: 300-1, width: 20, height: 20)
sleep(UInt32(0.3))
}while goingUp==true
repeat{
dotPic.frame = CGRect(x: 50, y: 300-1, width: 20, height: 20)
sleep(UInt32(0.3))
}while goingUp==false
}
rep()
}
}
I have tried using animateWithDuration() too but it has always frozen the app. What am I doing wrong?
Tried to use this code in swift...
self.hintImageView.frame = CGRect(x: x, y: 55, width: 200, height: 40)
UIView.animate(withDuration: 0.5, delay: 0, options: [.repeat, .autoreverse] , animations: {
self.hintImageView.frame = CGRect(x: x, y: 65, width: 200, height: 40);
}) { (completed) in
}
Here, Try this, instead of func rep() in your gameButtonAction :
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
//code with animation
dotPic.frame = CGRect(x: 50, y: 300-1, width: 20, height: 20)
} completion:^(BOOL finished) {
//code for completion
dotPic.frame = CGRect(x: 50, y: 300, width: 20, height: 20)
}];
and avoid using nested function rep() in your target. Probably it is running continuously causing your application to hang.

in Swift4, replacement of navigationItem.leftBarButtonItem resizes unwanted

Having a problem with UIBarButtonItem resizing when returning to VC with different values for frame and image.
var selectedR = 1
var leftFrame = CGRect()
var leftImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
if selectedR == 0
{
leftFrame = CGRect(x: 0, y: 0, width: 33, height: 33)
leftImage = UIImage(named: “pic-0”)!
}
else if selectedR == 1
{
leftFrame = CGRect(x: 0, y: 0, width: 79, height: 33)
leftImage = UIImage(named: "pic-1")!
}
else if selectedR == 2
{
leftFrame = CGRect(x: 0, y: 0, width: 34, height: 33)
leftImage = UIImage(named: "pic-2”)!
}
let cButton = UIButton(frame: leftFrame)
cButton.setImage(leftImage, for: UIControlState())
cButton.addTarget(self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)), for: .touchUpInside)
cButton.contentMode = UIViewContentMode.scaleAspectFit
let leftItem = UIBarButtonItem(customView: cButton)
self.navigationItem.leftBarButtonItem = leftItem
}
First time perfect size for selectedR = 1
Coming back into viewDidLoad with different selectedR value and image blows up, distorts and setting the leftFrame size is not honoured.
This all worked perfect in swift 3, but swift 4 it goes all over the place. Any help or suggestions would be much appreciated.
One major change between iOS 10 and 11 is now bar button items are laid out by the auto layout engine. Typically that should be backward compatible. But if you are having problems with laying out bar button items, you should try setting constraints and see if that solves your problem.
In you case you would say:
var selectedR = 1
var leftFrame = CGRect()
var leftImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
if selectedR == 0
{
leftFrame = CGRect(x: 0, y: 0, width: 33, height: 33)
leftImage = UIImage(named: “pic-0”)!
}
else if selectedR == 1
{
leftFrame = CGRect(x: 0, y: 0, width: 79, height: 33)
leftImage = UIImage(named: "pic-1")!
}
else if selectedR == 2
{
leftFrame = CGRect(x: 0, y: 0, width: 34, height: 33)
leftImage = UIImage(named: "pic-2”)!
}
let cButton = UIButton(frame: leftFrame)
cButton.widthAnchor.constraint(equalToConstant: leftFrame.width).isActive = true
cButton.heightAnchor.constraint(equalToConstant: leftFrame.height).isActive = true
cButton.setImage(leftImage, for: UIControlState())
cButton.addTarget(self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)), for: .touchUpInside)
cButton.contentMode = UIViewContentMode.scaleAspectFit
let leftItem = UIBarButtonItem(customView: cButton)
self.navigationItem.leftBarButtonItem = leftItem
}
This was covered in Apple's WWDC 2017 session Updating Your App for iOS 11.

Resources