Custom Class view and selector reference - ios

I'm making a custom class that just has some basic functions I can reuse once the class is initialized in any viewController. The problem is I don't know how to refer to the view or any functions being called in the #selector and I get the error: use of unresolved identifier "view". Anyone know how that's done? The sample below is to create a new UIButton.
import Foundation
import UIKit
class Utils {
var newUpdatesBtn: UIButton!
func setupButtonNewUpdates() {
newUpdatesBtn = UIButton(type: UIButtonType.System) // .System
newUpdatesBtn.setTitle("New Updates", forState: UIControlState.Normal)
newUpdatesBtn.bounds = CGRect(x: 0, y: 0, width: 123, height: 27)
newUpdatesBtn.center = CGPoint(x: view.bounds.width / 2, y: 90) // 80 point button, 20 point status bar, 40 point half button, 8 point margins
newUpdatesBtn.setBackgroundImage(UIImage(named: "new-updates"), forState: UIControlState.Normal)
newUpdatesBtn.titleLabel?.font = UIFont.systemFontOfSize(14)
newUpdatesBtn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
newUpdatesBtn.addTarget(self, action: #selector(newUpdatesButtonPressed), forControlEvents: UIControlEvents.TouchUpInside)
self.newUpdatesBtn.alpha = 0;
self.navigationController!.view.addSubview(newUpdatesBtn)
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.newUpdatesBtn.alpha = 1;
})
}
}
(problem lines)
view.bounds.width
newUpdatesBtn.addTarget(self, action: #selector(newUpdatesButtonPressed), forControlEvents: UIControlEvents.TouchUpInside)

This is because you have not set any reference in view property.
You can do like this:
func setupButtonNewUpdates(targetView:UIView)
{
newUpdatesBtn = UIButton(type: UIButtonType.System) // .System
.
.
.
newUpdatesBtn.center = CGPoint(x: targetView.bounds.width / 2, y: 90) // 80 point button, 20 point status bar, 40 point half button, 8 point margins
.
.
.
targetView.addSubView(newUpdatesBtn);
}
Now whenever you call this method from any viewcontroller just pass the view of that VC. for example:
var util:Utils = new Utils();
util.setupButtonNewUpdates(self.view);

Related

Swift Center Circle Button in TabbarViewController iOS

My scenario, I am trying to create centre circle button in UITabbarViewController. I tried many sample but not getting output like below Image. Please provide some code to achieve this. I am using storyboard for this.
sample Image
You need to do is your UITabbarViewController must contain five tabs in bottom tab bar that you can do by adding five view controller and make sure the middle tab contain no title and icon.
After that in onCreate method of your UITabbarViewController add this custom button Code -
let button = UIButton(type: .custom)
var toMakeButtonUp = 40
button.frame = CGRect(x: 0.0, y: 0.0, width: 65, height: 65)
button.setBackgroundImage(ADD, for: .normal)
button.setBackgroundImage(ADD, for: .highlighted)
let heightDifference: CGFloat = CGFloat(toMakeButtonUp)
if heightDifference < 0 {
button.center = tabBar.center
} else {
var center: CGPoint = tabBar.center
center.y = center.y - heightDifference / 2.0
button.center = center
}
button.addTarget(self, action: #selector(btnTouched), for:.touchUpInside)
view.addSubview(button)
FYI - toMakeButton is the margin from bottom you can set it accordingly.
and #selector(btnTouched) is the function defined in class which will perform on click on the button.

Assign tags for dynamic UIButtons

I found this example of a dynamic view of UIButtons at: http://helpmecodeswift.com/advanced-functions/generating-uibuttons-loop
I inserted this code into my app but unfortunately I can't find a way to set a tag for each buttons.
My target is to know which button is tapped, count the amount of clicks for each button and save this information into my DB.
override func viewDidLoad() {
super.viewDidLoad()
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
var buttonY: CGFloat = 20
for villain in arrayOfVillains {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGrayColor()
villainButton.setTitle("Button for Villain: \(villain)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
func villainButtonPressed(sender:UIButton!) {
if sender.titleLabel?.text != nil {
println("You have chosen Villain: \(sender.titleLabel?.text)")
} else {
println("Nowhere to go :/")
}
}
}
So how it is possible to set and get the tag for/from each button in code (in this example)?
Thank you in advance!
You can use enumerated array to access indexes of the current item in iteration and use that as a tag:
override func viewDidLoad() {
super.viewDidLoad()
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
var buttonY: CGFloat = 20
for (index, villain) in arrayOfVillains.enumerated() {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
// set the tag to current index
villainButton.tag = index
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGrayColor()
villainButton.setTitle("Button for Villain: \(villain)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
}
#objc func villainButtonPressed(sender:UIButton!) {
// tag of pressed button
print(">>> you pressed button with tag: \(sender.tag)")
if sender.titleLabel?.text != nil {
println("You have chosen Villain: \(sender.titleLabel?.text)")
} else {
println("Nowhere to go :/")
}
}
You should use an integer-based for loop for this.
for i in 0 ..< arrayOfVillains.count {
let villain = arrayOfVillains[i]
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
villainButton.tag = i
}
You can do as follows,
var buttonTag = 1
for villain in arrayOfVillains {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
villainButton.tag = buttonTag
buttonTag += 1
}

How can I properly place a UIButton on top of a loaded SFSafariViewController?

I have read many articles about the SFSafariViewController and I believe that it offers splendid functionality in iOS apps. However, when I load my SFSafariViewController, I intentionally hide the navigation bar because I want one custom fixed button in the upper left corner to dismiss the view controller.
override func viewDidAppear(_ animated: Bool) {
let safariViewController = PSSafariViewController(url: URL(string: blogUrl)!, entersReaderIfAvailable: true)
present(safariViewController, animated: false) {
var frame = safariViewController.view.frame
let OffsetY: CGFloat = 44
frame.origin = CGPoint(x: frame.origin.x, y: frame.origin.y - OffsetY)
frame.size = CGSize(width: frame.width, height: frame.height + OffsetY)
safariViewController.view.frame = frame
let btn: UIButton = UIButton(frame: CGRect(x: 100, y: 400, width: 100, height: 50))
btn.backgroundColor = UIColor.green
btn.setTitle("Click Me", for: .normal)
btn.addTarget(self, action: #selector(PSBlogViewController.buttonAction), for: UIControlEvents.touchUpInside)
btn.tag = 1 // change tag property
btn.isOpaque = true
safariViewController.view.addSubview(btn)
safariViewController.view.bringSubview(toFront: btn)
print(btn.description)
}
}
As you can see, I alter the frame so that the bar at the top is not visible. That code runs fine. But when I try to add a UIButton, it appears briefly and then is covered when I run the app. It's a simple blog reader app that uses the SFSafariViewController. Maybe Apple doesn't want developers running around messing with this, but any solutions or workarounds to make the button stay visible are greatly appreciated!
Here's the info about the button: 0x7f950b618db0; frame = (100 400; 100 50); tag = 1; layer = CALayer: 0x60000023ab60
Why don't you use one of the other WebView classes to get the extra functionalities you desire?
5.1.1 (iv) SafariViewContoller must be used to visibly present information to users; the controller may not be hidden or obscured by
other views or layers. Additionally, an app may not use
SafariViewController to track users without their knowledge and
consent.
It is definitely true that Apple won't want the SFSafariViewController to be obscured. However, I did figure out that when I present it, in the completion block I can add a button and what was causing trouble was that I had to increase the zPosition of the layer of the button's view like so:
present(safariViewController, animated: false) {
var frame = safariViewController.view.frame
let OffsetY: CGFloat = 44
frame.origin = CGPoint(x: frame.origin.x, y: frame.origin.y - OffsetY)
frame.size = CGSize(width: frame.width, height: frame.height + OffsetY)
safariViewController.view.frame = frame
self.btn = UIButton(frame: CGRect(x: 5, y: 50, width: 50, height: 50))
self.btn.layer.cornerRadius = 25
self.btn.backgroundColor = UIColor(red: 0, green: 170/255, blue: 240/255, alpha: 0.5)
self.btn.setTitle("←", for: .normal)
self.btn.addTarget(self, action: #selector(safariViewController.buttonAction(sender:)), for: .touchUpInside)
self.btn.tag = 1 // change tag property
self.btn.isOpaque = true
safariViewController.view.addSubview(self.btn)
safariViewController.view.bringSubview(toFront: self.btn)
self.btn.layer.zPosition = safariViewController.view.layer.zPosition + 1
for subview in safariViewController.view.subviews {
subview.isUserInteractionEnabled = false
}
self.btn.isEnabled = true
self.btn.isUserInteractionEnabled = true
//print(self.btn.description)
}

center element when pressed in a ScrollView

i really how to do a thing wich is probably easy..
I've a ScrollView with some button in it.
That's how i create all my button in the scrollview.
var buttonList = [UIButton]()
func createButton() {
let imageArray = fillImageArray()
var lastButtonWidth: CGFloat = 0
for index in 0..<6 {
let frame1 = CGRect(x: ((self.view.frame.size.width / 2) - 27.5) + CGFloat(index * 70), y: 0, width: 55, height: 55 )
let button = UIButton(frame: frame1)
button.setImage(imageArray[index], forState: .Normal)
button.tag = index
button.addTarget(parentViewController, action: #selector(ViewController.buttonClicked(_:)), forControlEvents: .TouchUpInside)
self.scrollView.addSubview(button)
lastButtonWidth = frame1.origin.x
buttonList.append(button)
}
self.scrollView.contentSize = CGSizeMake(lastButtonWidth + 55, 0)
}
I want when i press one of my button to center him and positioning correctly the other buttons.
example :
If i press on 5 i want this result :
the button 5 is moved to the center.
Now what I would suggest using is the scroll view method scrollView.scrollRectToVisible(CGRect, animated: Bool). This will move the scroll view to make a certain part of your content visible.
To create the CGRect you could do something like this:
let scrollWidth = scrollView.frame.width
let scrollHeight = scrollView.frame.height
let desiredXCoor = button.frame.origin.x - ((scrollWidth / 2) - (button.frame.width / 2) )
let rect = CGRect(x: desiredXCoor, y: 0, width: scrollWidth, height: scrollHeight)
scrollView.scrollRectToVisible(rect, animated: true)
My math may be a bit off, but the essence is that you use the size of the scrollView and the UIButton to create a CGRect for the scroll view to move to. This means when a button is clicked, you could use an implementation like this:
func myMethod() {
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonClicked(sender: UIButton){
let scrollWidth = scrollView.frame.width
let scrollHeight = scrollView.frame.height
let desiredXCoor = sender.frame.origin.x - ((scrollWidth / 2) - (sender.frame.width / 2) )
let rect = CGRect(x: desiredXCoor, y: 0, width: scrollWidth, height: scrollHeight)
scrollView.scrollRectToVisible(rect, animated: true)
}
If adjusted properly to your project, this should allow you to do what you have outlined.
Hope this would help you.
In button action method write below code.
func buttonClicked(sender:UIButton) {
for view in self.scrollView.subviews {
if view.isKindOfClass(UIButton) && view.tag == sender.tag {
let xCenter = max(0, (view.center.x - self.scrollView.frame.width/2))
self.scrollView.setContentOffset(CGPointMake(xCenter, self.scrollView.contentOffset.y), animated: true)
break;
}
}
}
I suppose you want the button touched to be placed in the center,so there is a easy solution, you can use the button's center.x - scrollview.width / 2 as the offsetX to construct the contentOffset and take two boundary situation into consideration:offsetx < 0 and offsetx + scrollview.width > scroll.contentSize.width
Ok i just found by myself.
let centerScrollView = scrollView.frame.size.height * 2
UIView.animateWithDuration(0.2, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: {
self.scrollView.contentOffset = CGPoint(x: sender.frame.origin.x - centerScrollView, y: sender.frame.origin.y)
}, completion: nil)
and it's perfectly center. Thx everyone.

How create buttonAction functions dynamically in Swift

In a MCQ app I create multiple UIButton programatically like this
func createNewButton(buttonName: String, xPosition: CGFloat, yPosition: CGFloat) -> UIButton {
let myButton = UIButton(frame: CGRectMake(0, 0, 50, 50))
myButton.center = CGPoint(x: xPosition, y: yPosition)
myButton.setImage(UIImage(named: buttonName), forState: UIControlState.Normal)
myButton.addTarget(self, action: "buttonName:", forControlEvents: UIControlEvents.TouchUpInside)
return myButton
}
The problem is that in order to match a function to these buttons I need to create a function. The function should therefore looks like
func buttonName(sender: UIButton!) {
// do some stuff
}
These functions are actually going to save a string in an array, and the string to save is the name of the function itself. If we have for example buttonName: "blackberry", the code is going to set an image called "blackberry" and add a target action named "blackberry" and I would like therefore a buttonAction function called func blackberry(sender: UIButton) and this function would save the string "blackberry" in an array of String.
But all of this should be done in function of the initial buttonName: String parameter.
Or maybe I am really not doing things the right way, and how should I do then?
How about this instead. Send all of your buttons to processButton(button: UIButton). When you create your buttons, set the tag property assigning a unique number to each button. Then you can have an array which translates the button tag to the string.
var buttonNames: [String] = []
var currentIndex = 0
func createNewButton(buttonName: String, xPosition: CGFloat, yPosition: CGFloat) -> UIButton {
let myButton = UIButton(frame: CGRectMake(0, 0, 50, 50))
myButton.center = CGPoint(x: xPosition, y: yPosition)
myButton.setImage(UIImage(named: buttonName), forState: UIControlState.Normal)
myButton.addTarget(self, action: "processButton:", forControlEvents: UIControlEvents.TouchUpInside)
myButton.tag = currentIndex++
self.buttonNames.append(buttonName)
return myButton
}
func processButton(button: UIButton) {
let string = buttonNames[button.tag]
// process string
}

Resources