import UIKit
public class SelectionItem: UIView {
var radioButtonController: SSRadioButtonsController
var stepper: KWStepper!
public init(){
let gcrRadioButton = SSRadioButton(frame: CGRect(x: 0, y: 100, width: 100, height: 50))
var decrementButton = UIButton(frame: CGRect(x: 400, y: 100, width: 50, height: 50))
var incrementButton = UIButton(frame: CGRect(x: 600, y: 100, width: 50, height: 50))
var countLabel = UILabel(frame: CGRect(x:500,y:100,width:50,height:50))
decrementButton.setImage(UIImage(named: "minus#2x.png"), forState: UIControlState.Normal)
incrementButton.setImage(UIImage(named: "plus#2x.png"), forState: UIControlState.Normal)
radioButtonController = SSRadioButtonsController(buttons: gcrRadioButton)
stepper = KWStepper(decrementButton: decrementButton, incrementButton: incrementButton)
stepper.delegate = self
stepper.valueChangedCallback = { [unowned self] stepper in
countLabel.text = String(format: "%.f", stepper.value)
}
super.init(frame: CGRectZero)
self.addSubview(gcrRadioButton)
self.addSubview(decrementButton)
self.addSubview(incrementButton)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("KWStepper: NSCoding is not supported!")
}
}
Question: Error occur at stepper.delegate = self. Cannot assign value of type SelectionItem to type KWStepperDelegate. KWStepper is a custom uicontrol class. How can i set delegation between two of them.
You have the delegate set to self, but as written self does not implement the delegate protocol. It should be:
public class SelectionItem: UIView, KWStepperDelegate
Then your SelectionItem must implement the delegate protocol.
Related
I recently started developing in Swift (normally embedded C developer).
I want to create some button (later more than one) programmatically and change its label (just for practice).
For this I created a button class, which contains the button init and the callback function. My problem is that it seems like the #selector is not pointing to the instance of the button class the way I expected it will, so a button click does nothing. Can you tell me what I am doing wrong?
#objc class buttontest : NSObject{
let button = NSButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
#objc func printSomething() {
print("Hello")
self.button.title="TEST13"
}
func buttoninit() -> NSButton{
self.button.title="Test"
self.button.bezelStyle=NSButton.BezelStyle.rounded
self.button.target=self;
//button.action = Selector(ViewController.printSomething)
self.button.action = #selector(self.printSomething)
return self.button
}
}
class ViewController: NSViewController {
private lazy var redBox = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redBox)
redBox.wantsLayer = true
redBox.layer?.backgroundColor = NSColor.red.cgColor
//button.init("Test12",self,Selector(printSomething())
let button = buttontest()
self.view.addSubview(button.buttoninit())
//self.view.addSubview(buttontest().buttoninit())
// Do any additional setup after loading the view.
}
override func loadView() {
self.view = NSView(frame: NSRect(x: 0, y: 0, width: NSScreen.main?.frame.width ?? 100, height: NSScreen.main?.frame.height ?? 100))
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
The OK version:
#objc class buttontest : NSObject{
let button = NSButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
#objc func printSomething() {
print("Hello")
self.button.title="TEST13"
}
func buttoninit() -> NSButton{
self.button.title="Test"
self.button.bezelStyle=NSButton.BezelStyle.rounded
self.button.target=buttonX
self.button.action = #selector(buttontest.printSomething)
return self.button
}
}
let buttonX = buttontest()
class ViewController: NSViewController {
private lazy var redBox = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redBox)
redBox.wantsLayer = true
redBox.layer?.backgroundColor = NSColor.red.cgColor
self.view.addSubview(buttonX.buttoninit())
}
}
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()
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()
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)
}
I created a subview from the ViewController. In the subview, multiple buttons are created. When any of the created buttons are tapped, I want to call the function buttonTapped() in the parent view controller.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var bestTeamEver = SFGiants(frame: CGRect(x: 0, y: 100, width: view.bounds.width, height: 40))
view.addSubview(bestTeamEver)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func buttonTapped(){
NSLog("BUTTON INSIDE SFGIANTS TAPPPED")
}
}
class SFGiants: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
for i in 0...10 {
var new_x = i*44
var button = UIButton(frame: CGRect(x: new_x, y: 0, width: 40, height: 40))
button.backgroundColor = UIColor.orangeColor()
// Call buttonTapped() in parent view controller
button.addTarget(self, action: "buttonTapped:", forControlEvents: UIControlEvents.TouchDown)
self.addSubview(button)
}
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
You can create a customize init method and can pass reference to parent viewController and set that to button target.
init(frame: CGRect actionListener:UIViewController) {
super.init(frame: frame)
for i in 0...10 {
var new_x = i*44
var button = UIButton(frame: CGRect(x: new_x, y: 0, width: 40, height: 40))
button.backgroundColor = UIColor.orangeColor()
// Call buttonTapped() in parent view controller
button.addTarget(actionListener, action: "buttonTapped:", forControlEvents: UIControlEvents.TouchDown)
self.addSubview(button)
}
}