(Swift 3) - How to include animations in custom UIView - ios

I have a UIView subclass called View, in which I want a "ripple" to move outwards from wherever the user double clicks (as well as preforming other drawing functions). Here is the relevant part of my draw method, at present:
override func draw(_ rect: CGRect) {
for r in ripples {
r.paint()
}
}
This is how r.paint() is implemented, in class Ripple:
func paint() {
let c = UIColor(white: CGFloat(1.0 - (Float(iter))/100), alpha: CGFloat(1))
print(iter, " - ",Float(iter)/100)
c.setFill()
view.fillCircle(center: CGPoint(x:x,y:y), radius: CGFloat(iter))
}
iter is supposed to be incremented every 0.1 seconds by a Timer which is started in the constructor of Ripple:
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: move)
move is implemented as follows:
func move(_ timer: Timer) {
while (tier<100) {
iter += 1
DispatchQueue.main.async {
self.view.setNeedsDisplay()
}
}
timer.invalidate()
}
What is supposed to happen is that every 0.1 seconds when the timer fires, it will increment iter and tell the View to repaint, which it will then do using the Ripple.paint() method, which uses iter to determine the color and radius of the circle.
However, as revealed using print statements, what happens instead is that the Timer fires all 100 times before the redraw actually takes place. I have tried dealing with this by replacing DispatchQueue.main.async with DispatchQueue.main.sync, but this just made the app hang. What am I doing wrong? If this is just not the right way to approach the problem, how can I get a smooth ripple animation (which involves a circle which grows while changing colors) to take place while the app can still preform other functions such as spawning more ripples? (This means that multiple ripples need to be able to work at once.)

You can achieve what you want with CABasicAnimation and custom CALayer, like that:
class MyLayer : CALayer
{
var iter = 0
override class func needsDisplay(forKey key: String) -> Bool
{
let result = super.needsDisplay(forKey: key)
return result || key == "iter"
}
override func draw(in ctx: CGContext) {
UIGraphicsPushContext(ctx)
UIColor.red.setFill()
ctx.fill(self.bounds)
UIGraphicsPopContext()
NSLog("Drawing, \(iter)")
}
}
class MyView : UIView
{
override class var layerClass: Swift.AnyClass {
get {
return MyLayer.self
}
}
}
class ViewController: UIViewController {
let myview = MyView()
override func viewDidLoad() {
super.viewDidLoad()
myview.frame = self.view.bounds
self.view.addSubview(myview)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let animation = CABasicAnimation(keyPath: "iter")
animation.fromValue = 0
animation.toValue = 100
animation.duration = 10.0
myview.layer.add(animation, forKey: "MyIterAnimation")
(myview.layer as! MyLayer).iter = 100
}
}

Custom UIView like AlertView with Animation for Swift 3 and Swift 4
You can use a extension:
extension UIVIew{
func customAlertView(frame: CGRect, message: String, color: UIColor, startY: CGFloat, endY: CGFloat) -> UIVIew{
//Adding label to view
let label = UILabel()
label.frame = CGRect(x: 0, y: 0, width: frame.width, height:70)
label.textAlignment = .center
label.textColor = .white
label.numberOfLines = 0
label.text = message
self.addSubview(label)
self.backgroundColor = color
//Adding Animation to view
UIView.animate(withDuration:0.5, delay: 0, options:
[.curveEaseOut], animations:{
self.frame = CGRect(x: 0, y: startY, width: frame.width, height: 64)
}) { _ in
UIView.animate(withDuration: 0.5, delay: 4, options: [.curveEaseOut], animations: {
self.frame = CGRect(x: 0, y: endY, width: frame.width, height:64)
}, completion: {_ in
self.removeFromSuperview()
})
}
return self
}
And you can use it un your class. This example startY is when you have a navigationController:
class MyClassViewController: UIViewController{
override func viewDidLoad(){
super.viewDidLoad()
self.view.addSubView(UIView().addCustomAlert(frame: self.view.frame, message: "No internet connection", color: .red, startY:64, endY:-64))
}
}

Related

Make custom-triggered UIColorPickerViewController hug bottom of screen?

I am using custom control to trigger the presentation of a UIColorPickerViewController. It triggers the color picker, but not as expected.
I was using UIColorWell previously, which does present the picker correctly (but it is an opaque implementation so I don't know how it does so). I don't want to use UIColorWell, because the shape and appearance aren't right for where I'm invoking the picker from.
Everything works exactly as desired except I can't get the color picker to present at the bottom of the screen like UIColorWell would do it. Instead, whatever I've tried to present (or show), UIColorPickerController appears near the top of the screen.
Note: Currently, to present the color picker controller, I'm using the latest iOS 15 trick with sheet controller / detents to try to anchor the picker to the bottom of the screen, but it's not working as expected (it's the technique is from the Apple Docs example, and as I've seen documented online).
What might be happening? What can I do to get the picker at the bottom of the screen, so that it doesn't obstruct my interface?
The Extension:
extension UIView {
func findViewController() -> UIViewController? {
if let nextResponder = self.next as? UIViewController {
return nextResponder
} else if let nextResponder = self.next as? UIView {
return nextResponder.findViewController()
} else {
return nil
}
}
}
Reproducible example (almost. It needs to be implemented/invoked from whatever VC [not shown here]):
This is custom control that that creates a rectangular color picker view (I'm using it to replace UIColorWell). It attempts to locate the VC which contains the view of which this custom control is a subview.
import UIKit
import QuartzCore
class RectangularColorWell : UIControl {
var colorPickerController = UIColorPickerViewController()
var selectedColor : UIColor = UIColor.clear
var lineWidth : CGFloat = 4.0 {
didSet {
self.setNeedsDisplay()
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
colorPickerController.supportsAlpha = false
colorPickerController.delegate = self
selectedColor = backgroundColor ?? UIColor.clear
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(CustomToggleControl.controlTapped(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.numberOfTouchesRequired = 1;
self.addGestureRecognizer(tapGestureRecognizer)
self.setNeedsDisplay()
}
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.setLineWidth(lineWidth)
ctx.setFillColor(backgroundColor!.cgColor)
ctx.fill(rect)
drawGradientBorder(rect, context: ctx)
}
func drawGradientBorder(_ rect: CGRect, context: CGContext) {
context.saveGState()
context.setLineWidth(lineWidth)
let path = UIBezierPath(rect: rect)
context.addPath(path.cgPath)
context.replacePathWithStrokedPath()
context.clip()
let rainbowColors : [UIColor] = [ .red, .orange, .yellow, .green, .blue, .purple ]
let colorDistribution : [CGFloat] = [ 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: rainbowColors.map { $0.cgColor } as CFArray, locations: colorDistribution)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0, y: 0), end: CGPoint(x: rect.width, y: rect.height), options: [])
context.restoreGState()
}
#objc func controlTapped(_ gestureRecognizer :UIGestureRecognizer) {
UIView.animate(withDuration: 0.2, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 0.5
}, completion: { (finished: Bool) -> Void in
UIView.animate(withDuration: 0.2, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.alpha = 1.0
}, completion: { (finished: Bool) -> Void in
})
})
setNeedsDisplay()
let vc = self.findViewController()
if let sheet = vc?.sheetPresentationController {
sheet.detents = [.medium()]
sheet.largestUndimmedDetentIdentifier = .medium
sheet.prefersScrollingExpandsWhenScrolledToEdge = false
sheet.prefersEdgeAttachedInCompactHeight = true
sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}
vc?.present(colorPickerController, animated: true, completion: nil)
sendActions(for: .touchDown)
}
}
extension RectangularColorWell : UIColorPickerViewControllerDelegate {
func colorPickerViewControllerDidFinish(_ controller : UIColorPickerViewController) {
self.selectedColor = controller.selectedColor
}
func colorPickerViewController(_ controller : UIColorPickerViewController, didSelect color: UIColor, continuously: Bool) {
self.backgroundColor = color
self.setNeedsDisplay()
}
}
#JordanH's final comment caused me to read up on the show/present methods on UIViewController docs. The default presentation style was what I'd been using (e.g. I hadn't set any of the presentation options on the color picker's view controller when I filed the question.
Surprisingly after reading that I could control the style, setting the picker's modalPresentationStyle property to '.pageSheet' which is the one that looks like it would work, to do a partial covering, did not work!.
The solution turned out to be adding colorPickerController.modalPresentationStyle = .popover before calling present()in the custom RectangularColorWellView). It now behaves as if it was presented from a UIColorWell control view.

Swift: Changing (translate) a UIView position through a pan gesture in its superview window

Introduction
Context:
In my main ViewController I have a scrollView with a few objects inside (which are UIViews). When one of the UIViews are tapped/selected I animate forward a UITextView in a UIView to go with the selected object. (only one UIView can appear at a time)
This UIView that appears on object selection is separated into a separate class called AdjunctiveTextView.
Issue/goal:
(the example code provided below will clear make this clear, I've also commented where the issue lies in the code)
When an object has been tapped and has an adjacent UIView with a text I want to have that adjacent UIView to follow with the scrollView.
I'm using a UIPanGestureRecognizer to attempt to do this. But I can't figure out how to make it work when the user drags in the scrollview. It only work if the user drags on the actual adjunctiveTextView.
Everything works as expected except that the adjunctiveTextView does not change its position during the panGesture.
I would like (if possible) to have the AdjunctiveTextView as a separate class. My ViewController file is getting rather big.
Question:
Why doesn't the UIPanGestureRecognizer work as expected? What is needed in order for it to translate the backView correctly?
Code
My attempt: (as shown below)
My attempt simply makes the backView itself "dragable" around through the panGesture. Nothing happens to it when I scroll the scrollView.
(I have only included relevant portions of my code)
class ViewController: UIViewController {
let adjunctiveTextView = AdjunctiveTextView()
// this is a delegate method which gets called when an object is tapped in the scrollView
func scrollViewObjectIsTapped(_ objectScrollView: ObjectScrollView, object: AvailableObject) {
** adjunctiveTextView.scrollView = scrollView // **Edited! (scrollView is the name of the scrollView in this class too)
adjunctiveTextView.showView(passInObject: AvailableObject)
}
}
class AdjunctiveTextView: NSObject {
lazy var backView: UIView = {
//backView setup
}
lazy var textView: UITextView = {
//textView setup
}
//additional init and setup
** weak var scrollView : UIScrollView! // **Edited!
func showView(passInObject: AvailableObject) {
if let window = UIApplication.shared.keyWindow {
// the issue must either be here in the PanGesture setup
let panG = UIPanGestureRecognizer(target: self, action: #selector(translateView(sender:)))
panG.cancelsTouchesInView = false
// window.addGestureRecognizer(panG)
** scrollView.addGestureRecognizer(panG) // **Edited!
window.addSubview(backView)
textView.text = passInObject.information
backView.frame = CGRect(x: passInObject.frame.minX, y: passInObject.minY, width: window.frame.width - passInObject.maxX - 6, height: textView.bounds.height + 5)
backView.alpha = 0
//it animates a change of the backViews x position and alpha.
UIView.animate(withDuration: 0.42, delay: 0, options: .curveEaseInOut, animations: {
self.backView.alpha = 1
self.backView.frame = CGRect(x: passInObject.frame.minX + passInObject.frame.width, y: passInObject.minY, width: window.frame.width - passInObject.maxX - 6, height: textView.bounds.height + 5)
}, completion: nil)
}
}
// or the issue is here in the handle function for the PanGesture.
#objc private func translateView(sender: UIPanGestureRecognizer) {
if let window = UIApplication.shared.keyWindow {
let translation = sender.translation(in: window) //Have tried setting this to scrollView also
switch sender.state {
case .began, .changed:
backView.center = CGPoint(x: backView.center.x, y: backView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: window) //Have tried setting this to sccrollView also
break
case .ended:
break
default:
break
}
}
}
}
Thanks for reading my question.
I just add a weak reference to your scrollView and then add the pan gesture to scrollView. It works as you want. You may consider add another pan gesture to the back view if you want your original behavior.
class AdjunctiveTextView: NSObject {
lazy var backView: UIView = {
//backView setup
return UIView.init()
}()
lazy var textView: UITextView = {
//textView setup
return UITextView.init(frame: CGRect.init(x: 0, y: 0, width: 300, height: 100))
}()
weak var scrollView: UIScrollView!
//additional init and setup
func showView(passInObject: AvailableObject) {
if let window = UIApplication.shared.keyWindow {
// the issue must either be here in the PanGesture setup
let panG = UIPanGestureRecognizer(target: self, action: #selector(translateView(sender:)))
panG.cancelsTouchesInView = false
// passInObject.addGestureRecognizer(panG)
scrollView.addGestureRecognizer(panG)
window.addSubview(backView)
textView.text = passInObject.information
textView.backgroundColor = UIColor.blue
backView.addSubview(textView)
backView.frame = CGRect(x: passInObject.frame.minX, y: passInObject.frame.minY, width: window.frame.width - passInObject.frame.maxX - 6, height: textView.bounds.height + 5)
backView.alpha = 0
//it animates a change of the backViews x position and alpha.
UIView.animate(withDuration: 0.42, delay: 0, options: .curveEaseInOut, animations: {
self.backView.alpha = 1
self.backView.frame = CGRect(x: passInObject.frame.minX + passInObject.frame.width , y: passInObject.frame.minY , width: window.frame.width - passInObject.frame.maxX - 6, height: self.textView.bounds.height + 5)
self.backView.backgroundColor = UIColor.red
}, completion: nil)
}
}
// or the issue is here in the handle function for the PanGesture.
#objc private func translateView(sender: UIPanGestureRecognizer) {
if let window = UIApplication.shared.keyWindow {
let translation = sender.translation(in: window)
switch sender.state {
case .began, .changed:
backView.center = CGPoint(x: backView.center.x, y: backView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: window)
break
case .ended:
break
default:
break
}
}
}
}
class ObjectScrollView: UIScrollView{
}
class AvailableObject: UIView{
var information: String!
}
class MySCNViewController: UIViewController {
#IBOutlet weak var oScrollView: ObjectScrollView!
// this is a delegate method which gets called when an object is tapped in the scrollView
func scrollViewObjectIsTapped(_ objectScrollView: ObjectScrollView, object: AvailableObject) {
adjunctiveTextView.showView(passInObject: object)
}
let adjunctiveTextView = AdjunctiveTextView()
let ao = AvailableObject.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 200))
override func viewDidLoad() {
super.viewDidLoad()
ao.information = "test"
adjunctiveTextView.scrollView = oScrollView
ao.backgroundColor = UIColor.yellow
}
#IBAction func tap(_ sender: Any?){
scrollViewObjectIsTapped(oScrollView, object: ao)}
}

Right margin of custom clear button in iOS

I create a custom clear button on my text field with a background image set.
I position it on the right view but it always positions with a default margin. What I want is to have a right margin, for example, of 8.
extension UITextField {
func clearButtonWithImage(_ image: UIImage) {
let clearButton = UIButton()
clearButton.setBackgroundImage(image, for: .normal)
clearButton.alpha = 0.25
clearButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
clearButton.contentMode = .scaleAspectFit
clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside)
self.rightViewMode = .always
self.clearButtonMode = .never
self.rightView = clearButton
}
#objc func clear(sender: AnyObject) {
self.text = ""
}
}
I use a custom textfield class for changing the style of my textfield on selecting.
My custom Textfield Class:
class customSearchTextField: customTextField {
override var isSelected: Bool {
didSet {
setSelected(isSelected)
}
}
private func setSelected(_ selected: Bool) {
//UIView.animate(withDuration: 0.15, animations: {
self.transform = selected ? CGAffineTransform(scaleX: 1.05, y: 1.05) : CGAffineTransform.identity
self.cornerRadius = selected ? 2.0 : 0.0
if selected {
self.clearButtonWithImage(UIImage())
} else {
self.clearButtonWithImage(#imageLiteral(resourceName: "icClear"))
}
self.layer.shadowColor = UIColor .customDark.cgColor
self.layer.shadowOpacity = selected ? 0.19 : 0.0
//})
}
}
Tried positioning the image frame but it always stays the same.
You should take a look at rightViewRect(forBounds:) method. Create a subclass of UITextField and custom position and size of clear button inside this method.
For example
class customSearchTextField: customTextField {
override var isSelected: Bool {
didSet {
setSelected(isSelected)
}
}
private func setSelected(_ selected: Bool) {
//UIView.animate(withDuration: 0.15, animations: {
self.transform = selected ? CGAffineTransform(scaleX: 1.05, y: 1.05) : CGAffineTransform.identity
self.cornerRadius = selected ? 2.0 : 0.0
if selected {
self.clearButtonWithImage(UIImage())
} else {
self.clearButtonWithImage(#imageLiteral(resourceName: "icClear"))
}
self.layer.shadowColor = UIColor .customDark.cgColor
self.layer.shadowOpacity = selected ? 0.19 : 0.0
//})
}
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
var rect = super.rightViewRect(forBounds: bounds)
rect.origin.x -= 30 // Assume your right margin is 30
return rect
}
}

Having some trouble making a custom UIActivityIndicatorView

I am trying my hand at creating a custom activity indicator view programatically. The problem is that it never starts animating. Here is the code for the spinner.swift class:
import UIKit
class spinner: UIActivityIndicatorView {
var flag = Bool()
override init(frame: CGRect) {
super.init(frame: frame)
self.flag = true
self.isHidden = false
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func startAnimating() {
self.animate()
}
func animate()
{
if flag == true
{
UIView.animate(withDuration: 0.3, animations: {
self.layer.setAffineTransform(CGAffineTransform(scaleX: 0.5, y: 1))
}) { (success) in
if success == true
{
UIView.animate(withDuration: 0.3, animations: {
self.layer.setAffineTransform(CGAffineTransform.identity)
}, completion: { (success) in
if success == true
{
self.animate()
}
})
}
}
}
}
override func stopAnimating() {
self.flag = false
}
override func draw(_ rect: CGRect) {
let path = UIBezierPath(ovalIn: rect)
UIColor.cyan.setStroke()
path.stroke()
UIColor.red.setFill()
path.fill()
}
}
This is the code in viewDidLoad() where I've added the spinner:
let aiv = spinner(frame: CGRect(x: self.view.bounds.width/2-35, y: self.view.bounds.height/2-35, width: 70, height: 70))
aiv.hidesWhenStopped = true
self.view.addSubview(aiv)
aiv.startAnimating()
print(aiv.isAnimating)
print(air)
I don't see a spinner at all, and get the following message in the console:
false
<spinner.spinner: 0x7f82b3e08240; baseClass = UIActivityIndicatorView; frame = (170 298.5; 35 70); transform = [0.5, 0, 0, 1, 0, 0]; hidden = YES; animations = { transform=<CABasicAnimation: 0x6080000364a0>; }; layer = <CALayer: 0x608000035120>>
According to the logs, the spinner is hidden, which means it never started animating.
It would be great if anyone could point out where I'm going wrong, and suggest a possible fix.
Thanks!
Your problem appears because of the call:
aiv.hidesWhenStopped = true
And the property isAnimating returns false because you are overriding the animate method and not use the foundation one.
You should set this property in your custom class when you are starting and stopping your custom animation.
The same case is the hidesWhenStopped. This should be implemented by you in your class.
I would also recommend to use UIView as a subclass with a UIActivityIndicator inside because if you want to start the ActivityIndicator the AffineTransformation could disrupt each other.

Vanishing popup alert view

I'd like to popup a view with a single label in it that disappears slowly within one second to inform the user about a choice he made, an update occurred or whatever.
I use animatewithduration, but because they may be many different alerts, I'd like to create a class to avoid creating view, label and func in any UIViewController that may display that kind of alert ... Kind of :
let doneAlert = PopUpAlert(parentView : self, textAlert : "You're done")
where parentView in the view where I want the textAlert to be displayed and then when needed:
doneAlert.display()
Here's the class I wrote :
class PopUpAlert: UIView {
convenience init(parentView : UIView,textAlert : String) {
self.init(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
self.alpha = 0
self.center = parentView.center
let popUpLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
popUpLabel.center = self.center
popUpLabel.text = textAlert
self.addSubview(popUpLabel)
parentView.addSubview(self)
}
func display() {
PopUpAlert.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.alpha = 1.0
}, completion: nil)
PopUpAlert.animateWithDuration(1.0, delay: 0.5, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.alpha = 0.0
}, completion: nil)
}
}
And here's the way I use it :
class CarteVC: UIViewController {
var daddy : RootViewController?
var goAlert : PopUpAlert?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
goAlert = PopUpAlert(parentView: mapView, textAlert: "On the way ....")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let bb = UIBarButtonItem(title: "< List", style: .Plain, target: papa!, action: "pred")
bb.tintColor = UIColor.lightGrayColor()
daddy!.navigationItem.leftBarButtonItem = bb
daddy!.navigationItem.rightBarButtonItem = nil
goAlert!.display()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
Nothing is displayed.
If you want to just alert user and disappear in one second than i would suggest you to use Toast Swift
https://github.com/scalessec/Toast-Swift
Here is how you make the toast
self.view.makeToast("Testing Toast")
// specific duration and position
self.view.makeToast("Testing Toast with duration and position", duration: 3.0, position: .Top)
// toast with image and all possible
self.view.makeToast("testing toast image and all possible ", duration: 2.0, position: CGPoint(x: 110.0, y: 110.0), title: "Toast Title", image: UIImage(named: "toast.png"), style:nil) { (didTap: Bool) -> Void in
if didTap {
print("with tap")
} else {
print("without tap")
}
}
The pb came from centering the label inside the view ... Here's the class and works perfectly fine !!! :
class PopUpAlert: UIView {
convenience init(parentView : UIView,textAlert : String) {
self.init(parentView: parentView,textAlert: textAlert,background: UIColor.darkGrayColor(),foreground: UIColor.whiteColor())
}
convenience init(parentView : UIView,textAlert : String, background : UIColor) {
self.init(parentView: parentView,textAlert: textAlert,background: background,foreground: UIColor.whiteColor())
}
convenience init(parentView : UIView,textAlert : String, foreground : UIColor) {
self.init(parentView: parentView,textAlert: textAlert,background: UIColor.darkGrayColor(),foreground: foreground)
}
convenience init(parentView : UIView,textAlert : String, background : UIColor, foreground : UIColor) {
self.init(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
self.alpha = 0
self.backgroundColor = background
self.layer.cornerRadius = 5
self.layer.masksToBounds = true
self.center = (parentView.superview ?? parentView).center
let popUpLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
popUpLabel.textAlignment = .Center
popUpLabel.textColor = foreground
popUpLabel.text = textAlert
self.addSubview(popUpLabel)
parentView.addSubview(self)
}
deinit {
self.removeFromSuperview()
}
func display() {
PopUpAlert.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.alpha = 0.85
}, completion: nil)
PopUpAlert.animateWithDuration(1.0, delay: 0.7, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.alpha = 0.0
}, completion: nil)
}

Resources