Animating a class that is an extension of UIView in Swift - swift

I'm trying to get an instance of my Options class to animate onto the screen using the function appear() which activates when pressing a button in my SearchResult class but I'm having trouble, the instance has been added as a subview to the view in the ViewController Class.
I've been able to use the function optionMenu.appear() in ViewController and that works as it should but not when it's called through clicking the button in SearchResult, it seems to do everything but the animation as I've tested printing in optionMenu.appear() and it successfully prints.
import Foundation
import UIKit
class SearchResult {
private let link: String
var body = UIView()
init(_ link: String){
self.link = link
let options = UIButton(x: Int(body.bounds.width-60), y: 10, size: 50.0)
options.addTarget(self, action: #selector(optionsClicked), for: .touchUpInside)
body.addSubview(options)
}
#objc func optionsClicked(){
ViewController().optionMenu.appear()
}
}
import Foundation
import UIKit
class Options: UIView{
var buttons = [UIButton]()
private var link = String()
init(_ titles: [String]){
let height = ((titles.count+1)*65)+5
super.init(frame: CGRect(x: 0, y: Int(UIScreen.main.bounds.height)-height, width: Int(UIScreen.main.bounds.width), height: height))
var i = 0
for title in titles{
let button = UIButton(frame: CGRect(x: 5, y: 5+(i*65), width: Int(UIScreen.main.bounds.width)-10, height: 60))
button.setTitle(title, for: .normal)
buttons.append(button)
self.addSubview(button)
i += 1
}
let cancel = UIButton(frame: CGRect(x: 5, y: 5+(i*65), width: Int(UIScreen.main.bounds.width)-10, height: 60))
cancel.setTitle("cancel", for: .normal)
self.addSubview(cancel)
}
func appear(){
UIView.animate(withDuration: 0.2, animations: {
self.transform = CGAffineTransform(translationX: 0, y: -self.bounds.height)
})
}
#objc func disappear(){
UIView.animate(withDuration: 0.2, animations: {
self.transform = CGAffineTransform.identity
})
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

It's because you are constructing a new Viewcontroller, and calling appear on that Viewcontroller's option menu every time optionsClicked() is called. You need a reference to the viewController that has the option menu and do myViewController.optionMenu.appear()

Related

“Unrecognized selector sent to instance” in UIView class when calling addTarget

I am trying to create a DropDownMenu class, but when I try to call addTarget to one of the buttons, this error comes up.
unrecognized selector sent to instance 0x7fd167f06120' terminating with uncaught exception of type NSException
I would really appreciate any help and no answer is a bad one!
Here is my entire class
class DropDownMenu: UIView {
// Main button or Pre
var main: UIButton! = UIButton(frame: CGRect(x: 0, y: 0, width: 46, height: 30))
var view: UIView!
// Title
var buttonTitles: [String]! = [""]
var titleColor: UIColor! = UIColor.black
var font: UIFont! = UIFont.systemFont(ofSize: 18)
// Individual Button
var buttonsBorderWidth: CGFloat! = 0
var buttonsBorderColor: UIColor? = UIColor.white
var buttonsCornerRadius: CGFloat! = 0
var color: UIColor! = UIColor.clear
// Button Images
var buttonsImageEdgeInsets: UIEdgeInsets? = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
var images: [UIImage]? = nil
// Onclick stuff
var target: UIViewController!
private var currentSelected: String? = nil
private var optionsStack = UIStackView()
init(main: UIButton) {
self.main = main
super.init(frame: CGRect())
}
func createDropDownMenu() {
main.addTarget(target, action: #selector(DropDownMenu.openDropdown(_:)), for: .touchUpInside)
print("Button Target?: \(main.allTargets), self.target: \(String(describing: target))")
let mainFrame = main.frame
optionsStack.frame = CGRect(x: mainFrame.minX, y: mainFrame.maxY, width: mainFrame.width, height: CGFloat(buttonTitles.count) * mainFrame.height)
optionsStack.axis = .vertical
view.addSubview(optionsStack)
var y: CGFloat! = 0
for title in buttonTitles {
let button = UIButton(frame: CGRect(x: 0, y: y, width: mainFrame.width, height: mainFrame.height))
button.setTitle(title, for: .normal)
button.setTitleColor(titleColor, for: .normal)
button.backgroundColor = color
button.titleLabel?.font = font
button.addTarget(target, action: #selector(DropDownMenu.onclick), for: .touchUpInside)
y += mainFrame.height
optionsStack.addArrangedSubview(button)
}
for button in optionsStack.arrangedSubviews {
button.isHidden = true
button.alpha = 0
}
}
#objc private func openDropdown(_ sender: UIButton) {
print("sender: \(String(describing: sender))")
optionsStack.arrangedSubviews.forEach { (button) in
UIView.animate(withDuration: 0.7) {
button.isHidden = !button.isHidden
button.alpha = button.alpha == 0 ? 1 : 0
self.view.layoutIfNeeded()
}
}
}
#objc private func onclick(_ sender: UIButton) {
let title = sender.titleLabel!.text
print(title as Any)
main.setTitle(title, for: .normal)
optionsStack.arrangedSubviews.forEach { (button) in
UIView.animate(withDuration: 0.7) {
button.isHidden = true
button.alpha = 0
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here is the code and creation of the object in ViewController
let grade = UIButton(frame: CGRect(x: 50, y: 300, width: 80, height: 30))
grade.layer.borderWidth = 1
grade.setTitle("Grade", for: .normal)
grade.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
grade.setTitleColor(UIColor.black, for: .normal)
let gradeDP = DropDownMenu(main: main)
gradeDP.buttonTitles = ["Title 1", "Title 2", "Title 3"]
gradeDP.color = UIColor.gray
gradeDP.target = self
gradeDP.titleColor = UIColor.white
gradeDP.view = view
view.addSubview(grade)
gradeDP.createDropDownMenu()
The first print statement in the createDropDownMenu() function prints...
Button Target?: [AnyHashable(<HomeworkHelp.DropDownMenu: 0x7ffb555200b0; frame = (0 0; 0 0); layer = <CALayer: 0x600002bdf5c0>>)], self.target: Optional(<HomeworkHelp.CreateAccountViewController: 0x7ffb5550a7b0>)
After editing it with the help of mightknow I came up with this class. It doesn't have any onclick actions for the mainButton in it.
class DropDownMenu: UIStackView {
var options: [String]! = [] // Labels for all of the options
var titleButton: UIButton! = UIButton() // The Main Title Button
init(options: [String]) {
self.options = options
let mainFrame = titleButton.frame
super.init(frame: CGRect(x: mainFrame.minX, y: mainFrame.maxY, width: mainFrame.width, height: mainFrame.height * CGFloat(options.count)))
var y: CGFloat = 0
for title in self.options {
let button = UIButton(frame: CGRect(x: 0, y: y, width: self.frame.width, height: mainFrame.height))
button.setTitle(title, for: .normal)
button.setTitleColor(titleButton.titleLabel?.textColor, for: .normal)
button.backgroundColor = titleButton.backgroundColor
button.addTarget(self, action: #selector(dropDownOptionClicked(_:)), for: .touchUpInside)
button.isHidden = true
button.alpha = 0
self.addArrangedSubview(button)
y += 1
}
}
#objc func openDropDown(_ sender: UIButton) {
print("Open DropDownMenu")
for button in self.arrangedSubviews {
UIView.animate(withDuration: 0.7) {
button.isHidden = !button.isHidden
button.alpha = button.alpha == 0 ? 1 : 0
self.layoutIfNeeded()
self.superview?.layoutIfNeeded()
}
}
}
#objc private func dropDownOptionClicked(_ sender: UIButton) {
print(sender.titleLabel?.text as Any)
}
init() {
super.init(frame: CGRect.zero)
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And than my ViewController is ...
let dp = DropDownMenu(options: ["Label 1", "Label 2", "Label 3"])
let titleButton = UIButton(frame: CGRect(x: 100, y: 300, width: 180, height: 40))
titleButton.backgroundColor = UIColor.white
titleButton.setTitle("DropDownMenu", for: .normal)
titleButton.setTitleColor(UIColor.black, for: .normal)
titleButton.layer.borderWidth = 2
titleButton.addTarget(self, action: #selector(dp.openDropDown(_:)), for: .touchUpInside)
dp.titleButton = titleButton
The error ...
Button Target?: [AnyHashable(<HomeworkHelp.DropDownMenu: 0x7ffb555200b0; frame = (0 0; 0 0); layer = <CALayer: 0x600002bdf5c0>>)], self.target: Optional(<HomeworkHelp.CreateAccountViewController: 0x7ffb5550a7b0>)
still comes up and I am clueless as to why.
You're setting the target as a UIViewController when the method you're calling is actually a method of the DropDownMenu class. What you need to do is set the target to self instead of the target property:
main.addTarget(self, action: #selector(DropDownMenu.openDropdown(_:)), for: .touchUpInside)
EDIT: In response to your comment, here is the code I'm using to test it. There are some layout/color choices I made just to make it clear to me, but this works:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let main = UIButton(frame: CGRect(x: 0, y: 100, width: 80, height: 30))
main.layer.borderWidth = 1
main.setTitle("Grade", for: .normal)
main.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
main.setTitleColor(UIColor.black, for: .normal)
let gradeDP = DropDownMenu(main: main)
gradeDP.buttonTitles = ["Title 1", "Title 2", "Title 3"]
gradeDP.color = UIColor.gray
gradeDP.target = self
gradeDP.titleColor = UIColor.white
gradeDP.view = UIView()
self.view.addSubview(gradeDP)
let b = self.view.bounds
gradeDP.frame = CGRect(x: b.minX, y: b.minY, width: b.width, height: b.height/2)
gradeDP.backgroundColor = UIColor.purple
gradeDP.target = self
gradeDP.addSubview(gradeDP.main)
gradeDP.createDropDownMenu()
}}
As for your code, I'm going on the assumption that the code you added in the second part of your question is inside your ViewController's viewDidLoad() method, and that the main variable you're using to initialize your DropDownMenu is an instance variable of your ViewController, because I'm not seeing it anywhere else in scope. If that's the case, there are definitely some issues. They are:
You never actually add gradeDP to your view hierarchy. If that's what the line gradeDP.view = view is supposed to do, it's not. What that code actually does is set the view property of gradeDP to be a reference to the ViewController's view property. And, unless there is code in your DropDownMenu class that you haven't included, you're not actually using that reference for anything. So, you can get rid of that line entirely, and the view property in your DropDownMenu class. If what you're trying to do is set the ViewController's view to be gradeDP, that code would be self.view = gradeDP, but I don't actually recommend doing it that way. A UIViewController's view property is used in some special functionality and probably shouldn't be messed with much. You probably want to add gradeDP as a subview, like I did in my code above.
The grade button you created is not used by your DropDownMenu. I'm guessing you meant to initialize with that instead of the main variable (that is out of scope of your code), like this:
let gradeDP = DropDownMenu(main: grade)
In short, unless there is code elsewhere that you haven't shared, what your code above does is create a UIButton labeled "Grade" that is visible but doesn't actually do anything (and isn't part of your DropDownMenu), and a DropDownMenu that isn't actually visible, but would have a main button that calls openDropdown(_:) if it was. I'm guessing that's not how it's supposed to work. Hopefully the code I provided above helps get you where you want to be, though.
As for suggestions with rebuilding your class so it works properly, you may want to start with something like this:
class DropDownMenu : UIView {
var dropdownOptions : [String] = []
private var titleButton : UIButton = UIButton()
private var optionsStack : UIStackView = UIStackView()
private var optionsButtons : [UIButton] = []
#objc private func openDropdown(_ sender: UIButton) {
// Add code to make dropdown options appear. There are multiple ways of doing this. For instance, the optionsButtons could be hidden and then unhidden when it's clicked, or they could be created only once the button is clicked.
}
#objc private func selectedOption(_ sender: UIButton) {
// Code here for when option is selected
}
init(options: [String]) {
self.dropdownOptions = options
super.init(frame: CGRect.zero)
// Customize all of your subviews here, and add them to your DropDownMenu (as subviews)
// Add openDropdown(_:) target to self.titleButton
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
A lot of the code you have already written for your original version of the class can go inside the functions there. Also, there is a lot of unnecessary code in your original version. For example, the target variable is unused once you fixed the original error issue, the view variable is obsolete, and the createDropDownMenu() function is unnecessary because all of that code can go either in the init(options:) or openDropdown(_:) functions.
Then, if you choose to build out a class using that template, you would implement it in your ViewController's viewDidLoad() method with the code:
let dropdown = DropDownMenu(titles: ["Title 1", "Title 2", "Title 3"])
self.view.addSubview(dropdown)
// Follow that with layout code that ensures it's the proper size and in the proper location
I hope that combined with my comments make sense, are helpful, and aren't too overwhelming. What I recommend doing is starting a new empty project (or target) and building your class and adding it to a ViewController with nothing else in it. That's a good way to isolate it and check and make sure everything looks and works right. In case you want an alternate suggestion with how to build your class, you can actually try making DropDownMenu be a subclass of UIStackView (instead of UIView) with the main button and all option buttons being arranged subviews. This might actually be simpler, because it kind of cuts out the middleman, if you will, and all you'd need to do when opening/closing the dropdown is add/remove views from the .arrangedSubviews property.
Also important is that if your view needs to pass information (such as which option is selected) back to the ViewController, make sure the reference to the ViewController is marked weak so you don't create a retain cycle.
On a final note, if you're disappointed that there isn't a quick fix to get the original class to work and want to keep trying at that, there might be some way to cobble together a solution (like the code from my first answer, which does actually work...), but ultimately it will probably only cause more issues further down the line. So, best of luck with everything.
I finally figured it out! The target has to be the DropDownMenu.
titleButton.addTarget(dp, action: #selector(dp.openDropDown(_:)), for: .touchUpInside)
Here is the rest of the code...
let titleButton = UIButton(frame: CGRect(x: 50, y: 290, width: 100, height: 40))
titleButton.backgroundColor = UIColor.white
titleButton.setTitle("Grade", for: .normal)
titleButton.setTitleColor(UIColor.black, for: .normal)
titleButton.layer.borderWidth = 2
titleButton.layer.cornerRadius = 10
let dp = DropDownMenu(options: ["1", "Freshman", "Sophomore", "Junior", "Senior", "College"])
dp.titleButton = titleButton
dp.target = self
dp.borderWidth = 2
dp.spacing = 5
dp.cornerRadius = 10
dp.bgColor = UIColor.white
Adding it to subviews and creating it...
view.addSubview(titleButton)
view.addSubview(dp)
dp.createDropDownMenu()

Adding a search bar to ui table view on overlay

I have managed to create, a dark overlay once clicked a search icon and have managed to add a table uiview on the dark overlay but now want to add a search bar within that table view. I cant seem to figure it out as my code seems different to everyone else's examples. I am new to swift so my code probably isn't the cleanest. can i ask if someone can show me how to do this as i am out of ideas. I have posted my code below can someone please show me where i'm going wrong.
Many thanks
class SearchLauncher: NSObject {
let blackView = UIView()
let tableView = UITableView()
#objc func showSearch() {
if let window = UIApplication.shared.keyWindow {
blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))
window.addSubview(blackView)
window.addSubview(tableView)
let height: CGFloat = 600
let y = window.frame.height - height
tableView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)
blackView.frame = window.frame
blackView.alpha = 0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.blackView.alpha = 1
self.tableView.frame = CGRect(x: 0, y: y, width: self.tableView.frame.width, height: self.tableView.frame.height)
}, completion: nil)
}
}
#objc func handleDismiss() {
UIView.animate(withDuration: 0.5) {
self.blackView.alpha = 0
if let window = UIApplication.shared.keyWindow {
self.tableView.frame = CGRect(x: 0, y: window.frame.height, width: self.tableView.frame.width, height: self.tableView.frame.height)
}
}
}
override init() {
super.init()
//start doing something here maybe
}
}```
How did you try to add a search controller?
I would do it by adding an UISearchController as a tableHeaderView of your table view. First make sure to add UISearchResultsUpdating protocol to your class.
class SearchLauncher: NSObject, UISearchResultsUpdating
Then add the search bar to your table view
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.sizeToFit()
searchController.searchResultsUpdater = self
//you probably don't need this
//searchController.dimsBackgroundDuringPresentation = false
tableView.tableHeaderView = searchController.searchBar
And then, implement the updateSearchResults(for:_) delegate method
func updateSearchResults(for searchController: UISearchController) {
filteredTableData.removeAll(keepingCapacity: false)
//filter the table data by using searchController.searchBar.text!
//filteredTableData = ...
self.tableView.reloadData()
}

Swift access helper function view

I try to access the function "addNavBar()" from, my helper class, but when I run the emulator, no view is shown on HomeViewController.
Swift 4
HomeViewController.swift
class HomeController: UIViewController {
let NavBar = NavigationBarHelper()
override func viewDidLoad() {
super.viewDidLoad()
NavBar.addNavBar()
}
}
NavigationBarHelper.swift
class NavigationBarHelper: UIView {
func addNavBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
self.addSubview(navBarView)
}
}
self in NavigationBarHelper is not the same object as the view in the view controller. Pass the VC's view as a parameter. There is no need to make NavigationBarHelper a subclass of UIView (in fact it could also be a struct).
class NavigationBarHelper {
func addNavBar(to view: UIView) {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
view.addSubview(navBarView)
}
}
please also stick to naming conventions
class HomeController: UIViewController {
let navBarHelper = NavigationBarHelper()
override func viewDidLoad() {
super.viewDidLoad()
navBarHelper.addNavBar(to: self.view)
}
Instead of creating an object every usage
let NavBar = NavigationBarHelper()
I think it's more robust to make it static like this
class NavigationBarHelper: UIView {
static func addNavBar(view:UIView) {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
view.addSubview(navBarView)
}
}
and call it directly without object creation
NavigationBarHelper.addNavBar(view: self.view)
A Better Alternative for this would be an extension so you don't have to create the special class for this
extension UIView {
func addNavBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
self.addSubview(navBarView)
}
}
And in you UIViewController you can simply write this without creating an object of your helper.
self.view.addNavBar()

Swift - detect touched coordinate of UIView

I am trying to make a custom jump bar which can be attached to UITableView.
What I want to achieve now is if user touches A and slides through Z, I want print out A, B, C, D..., Z. Currently, it only prints A, A, A...A. Is there anyway I can achieve it?
Each letter is UIButton subview of UIView.
class TableViewJumpBar{
let tableView: UITableView
let view: UIView
let jumpBar: UIView!
private var jumpIndexes: [Character]
init(tableView: UITableView, view: UIView){
self.view = view
self.tableView = tableView
jumpBar = UIView(frame: .zero)
jumpBar.backgroundColor = UIColor.gray
let aScalars = "A".unicodeScalars
let aCode = aScalars[aScalars.startIndex].value
jumpIndexes = (0..<26).map {
i in Character(UnicodeScalar(aCode + i)!)
}
}
func setFrame(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat){
guard jumpIndexes.count > 0 else{
print("Jump indexes cannot be empty")
return
}
//Remove jumpbar and remove all subviews
jumpBar.removeFromSuperview()
for subView in jumpBar.subviews{
subView.removeFromSuperview()
}
jumpBar.frame = CGRect(x: x, y: y, width: width, height: height)
let height = height/CGFloat(jumpIndexes.count)
for i in 0..<jumpIndexes.count{
let indexButton = UIButton(frame: CGRect(x:CGFloat(0.0), y: CGFloat(i)*height, width: width, height: height))
indexButton.setTitle(String(jumpIndexes[i]), for: .normal)
indexButton.addTarget(self, action: #selector(jumpIndexButtonTouched(_:)), for: .allEvents)
jumpBar.addSubview(indexButton)
}
self.view.addSubview(jumpBar)
}
///Touch has been begun
#objc private func jumpIndexButtonTouched(_ sender: UIButton!){
print(sender.titleLabel?.text)
}
this code works and print start and finish characters.
class ViewController: UIViewController {
#IBOutlet weak var myTableView: UITableView!
#IBOutlet weak var myView: UIView!
var startChar = ""
var finishChar = ""
override func viewDidLoad() {
super.viewDidLoad()
let table = TableViewJumpBar(tableView: myTableView, view: myView)
table.setFrame(x: 0, y: 0, width: 100, height: self.view.frame.size.height)
print(myView.subviews[0].subviews)
setPanGesture()
}
func setPanGesture() {
let pan = UIPanGestureRecognizer(target: self, action: #selector(panRecognized))
self.myView.addGestureRecognizer(pan)
}
#objc func panRecognized(sender: UIPanGestureRecognizer) {
let location = sender.location(in: myView)
if sender.state == .began {
for button in myView.subviews[0].subviews {
if let button = button as? UIButton, button.frame.contains(location), let startCharacter = button.titleLabel?.text {
self.startChar = startCharacter
}
}
} else if sender.state == .ended {
for button in myView.subviews[0].subviews {
if let button = button as? UIButton, button.frame.contains(location), let finishCharacter = button.titleLabel?.text {
self.finishChar = finishCharacter
}
}
print("start with \(startChar), finish with \(finishChar)")
}
}
}
In your code I delete Button action. you can use labels instead Buttons.
class TableViewJumpBar {
let tableView: UITableView
let view: UIView
let jumpBar: UIView!
private var jumpIndexes: [Character]
init(tableView: UITableView, view: UIView){
self.view = view
self.tableView = tableView
jumpBar = UIView(frame: .zero)
jumpBar.backgroundColor = UIColor.gray
let aScalars = "A".unicodeScalars
let aCode = aScalars[aScalars.startIndex].value
jumpIndexes = (0..<26).map {
i in Character(UnicodeScalar(aCode + i)!)
}
}
func setFrame(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat){
guard jumpIndexes.count > 0 else{
print("Jump indexes cannot be empty")
return
}
jumpBar.removeFromSuperview()
for subView in jumpBar.subviews{
subView.removeFromSuperview()
}
jumpBar.frame = CGRect(x: x, y: y, width: width, height: height)
let height = height/CGFloat(jumpIndexes.count)
for i in 0..<jumpIndexes.count{
let indexButton = UIButton(frame: CGRect(x:CGFloat(0.0), y: CGFloat(i)*height, width: width, height: height))
indexButton.setTitle(String(jumpIndexes[i]), for: .normal)
jumpBar.addSubview(indexButton)
}
self.view.addSubview(jumpBar)
}
}
Some output results:

Prog created Buttons from class don't appear - Swift IOS

I'm trying to add a number of customClass buttons to my view automatically, based on the size of an array.
Created the class and called the appropriate method in the class, but nothing shows up. Debugging tells me that the method is called/executed as expected (3x).
When I add the function directly to the view controller it does work.
What am I missing here ???
ViewController code:
import UIKit
class ViewController: UIViewController {
let userArray: [String] = ["One","Two","Three"]
override func viewDidLoad() {
super.viewDidLoad()
for item in userArray {
CustomCheckBox().showNewButton()
}
}
.. Other stuff...
}
CustomButton class code:
{
import UIKit
class CustomCheckBox: UIButton {
let checkedImage: UIImage = UIImage(named:"chckbox_on")!
let uncheckedImage: UIImage = UIImage(named: "chckbox_off")!
var newButton: CustomCheckBox!
..... other functions (isChecked, buttonClicked, ..)
func showNewButton (){
newButton = CustomCheckBox (type: UIButtonType.Custom)
newButton.bounds = CGRect(x: 0, y: 0, width: 45, height: 45)
newButton.center = CGPoint(x: 40, y: 40)
newButton.addTarget(newButton, action: #selector(CustomCheckBox.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
newButton.isChecked=false
self.addSubview(newButton)
}
}
May consider restructuring your code like this
class CustomCheckBoxContainer: UIView {
var newButton: CustomCheckBox!
func showNewButton (){
newButton = CustomCheckBox (type: UIButtonType.custom)
newButton.bounds = CGRect(x: 0, y: 0, width: 45, height: 45)
newButton.center = CGPoint(x: 40, y: 40)
newButton.addTarget(newButton, action: #selector(CustomCheckBox.buttonClicked(_:)), for: UIControlEvents.TouchUpInside)
newButton.isChecked=false
self.addSubview(newButton)
}
}
class CustomCheckBox: UIButton {
let checkedImage: UIImage = UIImage(named:"chckbox_on")!
let uncheckedImage: UIImage = UIImage(named: "chckbox_off")!
//add here all your button functionality
}
and then change your view did load to something like this:
override func viewDidLoad() {
super.viewDidLoad()
for item in userArray {
let customCheckBoxContainer = CustomCheckBoxContainer()
customCheckBoxContainer.showNewButton()
self.view.addSubview(customCheckBoxContainer)
}
}
pass your current View as parameter of your function like this.
override func viewDidLoad() {
super.viewDidLoad()
for item in userArray {
CustomCheckBox().showNewButton(self.view)
}
}
Modify your custom UIButton function newButton like this
func showNewButton (currentView : UIView){
newButton = CustomCheckBox (type: UIButtonType.Custom)
newButton.bounds = CGRect(x: 0, y: 0, width: 45, height: 45)
newButton.center = CGPoint(x: 40, y: 40)
newButton.addTarget(newButton, action: #selector(CustomCheckBox.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
newButton.isChecked=false
currentView.addSubview(newButton)
}