Subview Not Removing after Several "Remove View" Methods - swift

I have this nice function that adds an activity indicator view, with a regular view behind it. When I add it, it adds fine. The problem is, when I try to remove it, nothing happens. I've tried:
.removeFromSuperview,
.isHidden = true and putting these methods in the main queue:
DispatchQueue.main.async() {
alertView.alpha = 0
alertView.removeFromSuperview()
activityIndicator.removeFromSuperview()
alertView.isHidden = true
activityIndicator.isHidden = true
}
I don't know what other methods to try...It seems all the other questions like this have one of the methods that I have as a solution. The function uses a boolean to determine whether or not to stop the activityIndicator. Here is my code:
static func showLoadingView(inViewController: UIViewController, turning: Bool){
let activityIndicator = UIActivityIndicatorView()
let alertView = UIView(frame: CGRect(x: activityIndicator.frame.origin.x, y: activityIndicator.frame.origin.y , width: 35, height: 35))
if(turning){
alertView.backgroundColor = UIColor(displayP3Red: 230, green: 230, blue: 230, alpha: 0.8)
alertView.layer.cornerRadius = 5
activityIndicator.center = alertView.center
inViewController.view.addSubview(alertView)
activityIndicator.activityIndicatorViewStyle = .gray
activityIndicator.startAnimating()
alertView.alpha = 0
activityIndicator.backgroundColor = UIColor.lightGray
alertView.center = inViewController.view.center
alertView.addSubview(activityIndicator)
alertView.transform = CGAffineTransform.init(scaleX: 1.3,y: 1.3)
UIView.animate(withDuration: 0.4) {
alertView.alpha = 1
alertView.transform = CGAffineTransform.identity
}
}
///////
else {
activityIndicator.stopAnimating()
alertView.transform = CGAffineTransform.init(scaleX: 1.3, y:1.3)
DispatchQueue.main.async() {
alertView.alpha = 0
alertView.removeFromSuperview()
activityIndicator.removeFromSuperview()
alertView.isHidden = true
activityIndicator.isHidden = true
}
print("Done")
}
}

You declared alertView which is out of scope when you called false.As a result, your call could not identify the alertView instance.
You can solve this issue in tow ways:
Declare your alertView outside of the function as a static.
static let activityIndicator = UIActivityIndicatorView()
static let alertView = UIView(frame: CGRect(x: activityIndicator.frame.origin.x, y: activityIndicator.frame.origin.y , width: 35, height: 35))
static func showLoadingView(inViewController: UIViewController, turning: Bool){}
In false case: find the subview using restorationIdentifier and remove.
static func showLoadingView(inViewController: UIViewController, turning: Bool){
if(turning){
let activityIndicator = UIActivityIndicatorView()
let alertView = UIView(frame: CGRect(x: activityIndicator.frame.origin.x, y: activityIndicator.frame.origin.y , width: 35, height: 35))
alertView.restorationIdentifier = "myalert"
alertView.backgroundColor = UIColor(displayP3Red: 230, green: 230, blue: 230, alpha: 0.8)
alertView.layer.cornerRadius = 5
activityIndicator.center = alertView.center
inViewController.view.addSubview(alertView)
activityIndicator.activityIndicatorViewStyle = .gray
activityIndicator.startAnimating()
alertView.alpha = 0
activityIndicator.backgroundColor = UIColor.lightGray
alertView.center = inViewController.view.center
alertView.addSubview(activityIndicator)
alertView.transform = CGAffineTransform.init(scaleX: 1.3,y: 1.3)
UIView.animate(withDuration: 0.4) {
alertView.alpha = 1
alertView.transform = CGAffineTransform.identity
}
}
///////
else {
for view in inViewController.view.subviews {
if (view.restorationIdentifier == "myalert") {
print("I FIND IT");
(view as! UIView).removeFromSuperview();
}
}
}
}

Related

Getting trouble when hovering a custom segmented control in swift

I tried to create custom segmented control which should change its look if you are hovering it. But it does not work as I expected.
Here's the code (I am sorry that it is that long but I already made it 200 lines shorter then it was):
class MySegmentedControl: UIView {
var state = MySegmentedControl_State.unknown
var buttons = [MySegmentedControl_ButtonView]()
func setUpView(){
let view = UIView(frame: self.frame)
view.frame.origin.x = 0
view.frame.origin.y = 0
view.addSubview(holderView())
self.addSubview(view)
}
func holderView() -> UIView{
let view = UIView(frame: CGRect(origin: CGPoint(x: 100, y: 0), size: CGSize(width: 490, height: 70)))
view.layer.borderWidth = 5
view.layer.borderColor = UIColor.gray.cgColor
view.layer.cornerRadius = view.frame.height / 2
view.layer.masksToBounds = true
view.clipsToBounds = true
view.backgroundColor = #colorLiteral(red: 0.5741485357, green: 0.5741624236, blue: 0.574154973, alpha: 1)
//place the first button
let button_1 = MySegmentedControl_ButtonView(text: "One", frame: CGRect(x: 0, y: 0, width: 163.3333, height: 70), type: .one, delegate: self)
//place the second Button
let button_2 = MySegmentedControl_ButtonView(text: "Two", frame: CGRect(x: 163.3333, y: 0, width: 163.3333, height: 70), type: .two, delegate: self)
//place the third Button
let button_3 = MySegmentedControl_ButtonView(text: "Three", frame: CGRect(x: 163.3333*2, y: 0, width: 163.3333, height: 70), type: .three, delegate: self)
buttons.append(button_1); buttons.append(button_2); buttons.append(button_3)
view.addSubview(button_1)
view.addSubview(button_2)
view.addSubview(button_3)
return view
}
class MySegmentedControl_ButtonView: UIView{
private var selected = false
private var hovering = false
var text = ""
private var type: MySegmentedControl_State
private var delegate: MySegmentedControl_ButtonView_Delegate
private var label = UILabel()
func setUpView(){
layer.cornerRadius = frame.height/2
let label = UILabel(frame: frame)
self.label = label
label.tintColor = .white
label.text = text
label.sizeToFit()
label.center = self.center
label.font = label.font.withSize(15)
let regionizer = UIHoverGestureRecognizer(target: self, action: #selector(didHover(_:)))
addGestureRecognizer(regionizer)
addSubview(label)
//set up the button
let button = UIButton(frame: bounds, primaryAction: UIAction(handler: { [self] action in
selected = true
delegate.shouldChangeState(to: type)
delegate.shouldDeselectOthers(without: text)
if !hovering{
backgroundColor = #colorLiteral(red: 0.9961533629, green: 0.9931518435, blue: 1, alpha: 0.8)
}else{
self.backgroundColor = #colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 0.9435433103)
}
}))
addSubview(button)
}
func deselect(){
self.selected = false
if hovering{
backgroundColor = #colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 0.15)
UIView.animate(withDuration: 0.2) {[self]in
label.frame.origin.y = 10
label.font = label.font.withSize(12)
}
}else{
backgroundColor = #colorLiteral(red: 0.2605174184, green: 0.2605243921, blue: 0.260515637, alpha: 0.15)
UIView.animate(withDuration: 0.2) {[self]in
label.frame.origin.y = 10
label.font = label.font.withSize(12)
}
}
}
#objc
func didHover(_ recognizer: UIHoverGestureRecognizer){
switch recognizer.state{
case .began, .changed:
hovering = true
if selected{
backgroundColor = #colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 0.15)
UIView.animate(withDuration: 0.2) {[self]in
label.frame.origin.y = 10
label.font = label.font.withSize(12)
}
}else{
backgroundColor = #colorLiteral(red: 0.2605174184, green: 0.2605243921, blue: 0.260515637, alpha: 0.15)
UIView.animate(withDuration: 0.2) {[self]in
label.frame.origin.y = 10
label.font = label.font.withSize(12)
}
}
case .ended:
hovering = false
if selected{
self.backgroundColor = #colorLiteral(red: 0.9961533629, green: 0.9931518435, blue: 1, alpha: 0.2)
UIView.animate(withDuration: 0.2) {[self]in
label.center.y = center.y
label.font = label.font.withSize(15)
}
}else{
self.backgroundColor = .clear
UIView.animate(withDuration: 0.2) {[self]in
label.center.y = center.y
label.font = label.font.withSize(15)
}
}
default:break
}
}
init(text: String, frame: CGRect, type: MySegmentedControl_State, delegate: MySegmentedControl_ButtonView_Delegate){
self.type = type
self.delegate = delegate
super.init(frame: frame)
self.text = text
setUpView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}
extension MySegmentedControl: MySegmentedControl_ButtonView_Delegate{
func shouldDeselectOthers(without: String) {
for button in buttons{
if button.text != without{
button.deselect()
}
}
}
func shouldChangeState(to state: MySegmentedControl_State) {
self.state = state
}
}
protocol MySegmentedControl_ButtonView_Delegate{
func shouldDeselectOthers(without: String)
func shouldChangeState(to state: MySegmentedControl_State)
}
enum MySegmentedControl_State: String{
case unknown = "Non specific case avalaible"
case one = "One selected"
case two = "Two selected"
case three = "Three selected"
}
But the second of my buttons is displayed as the third and the the third does not get displayed, but if I hover the place where button two SHOULD be, it still gets hovered.
Here is a shout video:
Video showing problems with this code
My App is running on MacOS with MacCatalyst
In setUpView() inside class MySegmentedControl_ButtonView, you are trying to set the label's position with:
label.center = self.center
However, self.center is relative to self's superview. So your labels are being shifted.
If you change that line to:
label.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
the label centering will be correct.
As I asked in my comment though... why aren't you using auto-layout? It would make things much easier (and much more flexible).

Swift How to make the previous label disappear and the new one to appear

I’m making my first project that is a truth or dare game but when I tap the button to print a Truth/dare the labels are getting stacked on each other. How do I make it that the previous label disappear and the new one is there alone. Thanks in advance
import UIKit
import PlaygroundSupport
public class ViewController: UIViewController {
public override func loadView() {
//adding baground
super.loadView()
let view = UIView()
view.backgroundColor = .red
self.view = view
//dare button
let dareButton = UIButton(frame: CGRect(x:300, y: 500, width: 100, height: 69))
dareButton.layer.cornerRadius = 10
dareButton.backgroundColor = #colorLiteral(red: 0.6352941393852234, green: 0.6470588445663452, blue: 0.886274516582489, alpha: 1.0)
dareButton.setTitle("dare", for: UIControl.State.normal)
dareButton.isUserInteractionEnabled = true
dareButton.addTarget(self, action: #selector(dareButtonDidTap), for: .touchDown)
view.addSubview(dareButton)
self.view = view
view.addSubview(dareButton)
}
#objc
private func dareButtonDidTap() {
let lbl = UILabel(frame: CGRect(x:95 , y:100, width: 325, height: 500))
lbl.text = daresEng.randomElement()
lbl.textColor = #colorLiteral(red: 0.6313725709915161, green: 0.6470588445663452, blue: 0.9058823585510254, alpha: 1.0)
lbl.numberOfLines = 6
view.addSubview(lbl)
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()
The labels are stacked because you create a new label and add it to the view each time you click the dareButton, and the previous labels are not removed from the superView. So you can move the label to the class level and add it to the view in loadView(). This way you only have one label, and in the dareButtonDidTap(), you only have to change the text of this label.
import UIKit
import PlaygroundSupport
public class ViewController: UIViewController {
let lbl = UILabel(frame: CGRect(x:95 , y:100, width: 325, height: 500))
public override func loadView() {
//adding baground
super.loadView()
let view = UIView()
view.backgroundColor = .red
self.view = view
//dare button
let dareButton = UIButton(frame: CGRect(x:300, y: 500, width: 100, height: 69))
dareButton.layer.cornerRadius = 10
dareButton.backgroundColor = #colorLiteral(red: 0.6352941393852234, green: 0.6470588445663452, blue: 0.886274516582489, alpha: 1.0)
dareButton.setTitle("dare", for: UIControl.State.normal)
dareButton.isUserInteractionEnabled = true
dareButton.addTarget(self, action: #selector(dareButtonDidTap), for: .touchDown)
view.addSubview(dareButton)
self.view = view
view.addSubview(lbl)
view.addSubview(dareButton)
}
#objc
private func dareButtonDidTap() {
lbl.text = daresEng.randomElement()
lbl.textColor = #colorLiteral(red: 0.6313725709915161, green: 0.6470588445663452, blue: 0.9058823585510254, alpha: 1.0)
lbl.numberOfLines = 6
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()

CustomAlert Message overWrite

my model :
struct Model : Codable {
let title : String
var target : Int
var read : Int
let mean : String
let useful : String
}
and I create custom alert messages model:
class MyAlert {
struct Constants {
static let backgroundAlphaTo : CGFloat = 0.6
}
private var backgroundView : UIView = {
let backgroundView = UIView()
backgroundView.backgroundColor = .black
backgroundView.alpha = 0
return backgroundView
}()
private let alertView : UIView = {
let alertView = UIView()
alertView.backgroundColor = .white
alertView.layer.masksToBounds = true
alertView.layer.cornerRadius = 12
return alertView
}()
private var myTargetView : UIView?
func showAlert(with title :String , message : String , on ViewController : UIViewController){
guard let targetView = ViewController.view else {
return
}
myTargetView = targetView
backgroundView.frame = targetView.bounds
targetView.addSubview(backgroundView)
targetView.addSubview(alertView)
alertView.frame = CGRect(
x: 40, y: -300, width: targetView.frame.size.width-80, height: 300
)
let titleLabel = UILabel(frame: CGRect(
x: 0,
y: 0,
width: alertView.frame.size.width,
height: 80))
titleLabel.text = title
titleLabel.textAlignment = .center
alertView.addSubview(titleLabel)
let messageLabel = UILabel(frame: CGRect(
x: 0,
y: 80,
width: alertView.frame.size.width,
height: 170))
messageLabel.numberOfLines = 0
messageLabel.text = message
messageLabel.textAlignment = .center
alertView.addSubview(messageLabel)
let button = UIButton(frame: CGRect(
x: 0,
y: alertView.frame.size.height-50,
width: alertView.frame.size.width,
height: 50))
alertView.addSubview(button)
button.setTitle("Kapat", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.addTarget(self, action: #selector(dissmissAlert), for: .touchUpInside)
UIView.animate(withDuration: 0.25) {
self.backgroundView.alpha = Constants.backgroundAlphaTo
} completion: { (done) in
if done {
UIView.animate(withDuration: 0.25) {
self.alertView.center = targetView.center
}
}
}
}
#objc func dissmissAlert() {
guard let targetView = myTargetView else {
return
}
UIView.animate(withDuration: 0.25, animations: {
self.alertView.frame = CGRect(
x: 40, y: targetView.frame.size.height, width: targetView.frame.size.width-80, height: 300
)}, completion: {done in
if done {
UIView.animate(withDuration: 0.25, animations: {
self.backgroundView.alpha = 0
}, completion: {done in
if done {
self.alertView.removeFromSuperview()
self.backgroundView.removeFromSuperview()
}
})
}
}
)
}
}
and I have segmentController :
#objc func ButtonTapped( _ sender : UISegmentedControl) {
if sender.selectedSegmentIndex == 1 {
customAlert.showAlert(with: zikirs.title, message: zikirs.mean, on: self)
} else if sender.selectedSegmentIndex == 2 {
customAlert.showAlert(with: zikirs.title, message: zikirs.useful, on: self)
}
}
private func dismissAlert(){
customAlert.dissmissAlert()
}
the problem here is the first message is normal but the second message overwrites the other.
how can I overcome this problem. I think this is from the inheritance property of the Classes. but I wanted to do my CustomAlert model with Struct because #objc can be only classes
The problem is that you don't remove the labels and the button from alertView but add new ones on the next call.
My suggestion is to assign tags to the views and create them only the first time
class MyAlert {
struct Constants {
static let backgroundAlphaTo : CGFloat = 0.6
}
private var backgroundView : UIView = {
let backgroundView = UIView()
backgroundView.backgroundColor = .black
backgroundView.alpha = 0
return backgroundView
}()
private let alertView : UIView = {
let alertView = UIView()
alertView.backgroundColor = .white
alertView.layer.masksToBounds = true
alertView.layer.cornerRadius = 12
return alertView
}()
private var myTargetView : UIView?
func showAlert(with title :String , message : String , on ViewController : UIViewController){
guard let targetView = ViewController.view else {
return
}
myTargetView = targetView
backgroundView.frame = targetView.bounds
targetView.addSubview(backgroundView)
targetView.addSubview(alertView)
alertView.frame = CGRect(
x: 40, y: -300, width: targetView.frame.size.width-80, height: 300
)
if let titleLabel = alertView.viewWithTag(100) as? UILabel {
titleLabel.text = title
} else {
let titleLabel = UILabel(frame: CGRect(
x: 0,
y: 0,
width: alertView.frame.size.width,
height: 80))
titleLabel.tag = 100
titleLabel.text = title
titleLabel.textAlignment = .center
alertView.addSubview(titleLabel)
}
if let messageLabel = alertView.viewWithTag(101) as? UILabel {
messageLabel.text = message
} else {
let messageLabel = UILabel(frame: CGRect(
x: 0,
y: 80,
width: alertView.frame.size.width,
height: 170))
messageLabel.tag = 101
messageLabel.numberOfLines = 0
messageLabel.text = message
messageLabel.textAlignment = .center
alertView.addSubview(messageLabel)
}
if alertView.viewWithTag(102) == nil {
let button = UIButton(frame: CGRect(
x: 0,
y: alertView.frame.size.height-50,
width: alertView.frame.size.width,
height: 50))
button.tag = 102
alertView.addSubview(button)
button.setTitle("Kapat", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.addTarget(self, action: #selector(dissmissAlert), for: .touchUpInside)
}
UIView.animate(withDuration: 0.25) {
self.backgroundView.alpha = Constants.backgroundAlphaTo
} completion: { (done) in
if done {
UIView.animate(withDuration: 0.25) {
self.alertView.center = targetView.center
}
}
}
}
#objc func dissmissAlert() {
guard let targetView = myTargetView else {
return
}
UIView.animate(withDuration: 0.25, animations: {
self.alertView.frame = CGRect(
x: 40, y: targetView.frame.size.height, width: targetView.frame.size.width-80, height: 300
)}, completion: {done in
if done {
UIView.animate(withDuration: 0.25, animations: {
self.backgroundView.alpha = 0
}, completion: {done in
if done {
self.alertView.removeFromSuperview()
self.backgroundView.removeFromSuperview()
}
})
}
}
)
}
}

Cannot hide view after animation

I am creating an animation which brings an image and a label from the left to the centre of the view.
imageLogo.isHidden = true is not hidden when App is run
labelLogo is not shown at all on the view
I have been reading tutorials, but I just don't see what is wrong with my code.
let paymentLogo = UIImage(named: "paymentImage")
var imageLogo:UIImageView!
var overlayView = UIView()
var logoAppeared:Bool!
let labelLogo = UILabel()
override func viewDidLayoutSubviews() {
//move picture off the screen here
self.imageLogo = UIImageView(image:paymentLogo)
imageLogo.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
imageLogo.center.x -= 400
self.view.addSubview(imageLogo)
self.labelLogo.frame =
CGRect(x: 0, y: 0, width: 200, height: 21)
self.labelLogo.center.x -= 400
self.labelLogo.text = "Booking Completed"
self.labelLogo.textAlignment = .center
self.view.addSubview(labelLogo)
}
override func viewDidAppear(_ animated: Bool) {
UIView.animate(withDuration: 2.0, delay: 0.1, options: [], animations: {
//animate paymentCompletedLogo
self.overlayView = UIView(frame: self.view.frame)
self.overlayView.backgroundColor = UIColor.black
self.overlayView.alpha = 0.4
//animate labelLogo
self.labelLogo.frame = CGRect(x: self.view.center.x, y: 90, width: 200, height: 21)
self.labelLogo.backgroundColor = UIColor.gray
self.labelLogo.text = "Booking Completed"
self.labelLogo.textColor = .black
self.labelLogo.textAlignment = .center
//animate imageLogo
self.imageLogo.frame =
CGRect(x: self.view.center.x,y: self.view.center.y,width: 100,height: 100)
self.view.addSubview(self.overlayView)
self.view.addSubview(self.imageLogo)
self.view.addSubview(self.labelLogo)
}) { finished in
self.overlayView.isHidden = true
self.imageLogo.isHidden = true //it is not hidden in simulator
self.logoAppeared = true
}
}
I tried removing following your code from animation method it worked fine.
You are trying to add subview in animation method. imageLogo and labelLogo is all ready added in view.
self.view.addSubview(self.overlayView)
self.view.addSubview(self.imageLogo)
self.view.addSubview(self.labelLogo)

UIView is not hidden when condition is met in if else statement

I am trying to create an animation and hide it 5 seconds after the task has been completed.
For some reason overlayView is not hidden off the screen when counter == 5.
var counter = 0
var timer = Timer()
let paymentLogo = UIImage(named: "paymentImage")
var imageLogo:UIImageView!
var overlayView = UIView()
var logoAppeared:Bool? = false
let labelLogo = UILabel()
override func viewDidLayoutSubviews() {
//move picture off screen
animateDidLayout()
}
override func viewDidAppear(_ animated: Bool) {
//move picture on screen and adjust view
animateDidAppear()
}
//called by timer every 1 seconds
func startCounting() {
if counter == 5 {
self.timer.invalidate()
self.overlayView.isHidden = true //it is not hidden
self.imageLogo.isHidden = true
self.labelLogo.isHidden = true
self.logoAppeared = true
print("counter in if \(counter)")
} else {
counter += 1
print("counter in else \(counter)")
}
}
//animate the image before it appears on screen
func animateDidLayout(){
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidLayoutSubviews, in else")
return
}
print("appeared value after else in ViewDidLayoutSubvies \(appeared)")
//animate overlayView
self.overlayView = UIView(frame: self.view.frame)
self.overlayView.backgroundColor = UIColor.black
self.overlayView.alpha = 0.4
self.view.addSubview(self.overlayView)
//animate imageLogo
self.imageLogo = UIImageView(image:paymentLogo)
imageLogo.frame = CGRect(x: 0, y: 0, width: 100,
height: 100)
imageLogo.center.x -= 400
self.view.addSubview(imageLogo)
//animate labelLogo
self.labelLogo.frame =
CGRect(x: 0, y: 0, width: 200, height: 21)
self.labelLogo.center.x -= 400
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textAlignment = .center
self.view.addSubview(labelLogo)
}//end of animateDidLayout
//animate the logo when the view has appeared
//call it in ViewDidAppear
func animateDidAppear() {
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidAppear, in else")
return
}
print("appeared value in viewDidAppear after else \(appeared)")
UIView.animate(withDuration: 1.0, delay: 0.1, options: [],
animations: {
//animate overlayView
// self.overlayView = UIView(frame: self.view.frame)
//self.overlayView.backgroundColor = UIColor.black
//self.overlayView.alpha = 0.4
//animate labelLogo
self.labelLogo.frame = CGRect(x: self.view.center.x - 100,
y: 340, width: 200, height: 21)
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textColor = .white
self.labelLogo.textAlignment = .center
self.labelLogo.sizeToFit()
//animate imageLogo
self.imageLogo.frame =
CGRect(x: self.view.center.x - 50,y: 250,width: 100,height: 90)
}) { finished in
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self,
selector: #selector(ThirteenthViewController.startCounting), userInfo: nil,
repeats: true)
}
} //end of animateDidAppear
I would either use a delay or use another animation with a delay to remove hide the views. I would not rely on the timer. Example with animation to remove using your code and removing the timer.
class ViewController: UIViewController {
var counter = 0
let paymentLogo = UIImage(named: "paymentImage")
var imageLogo:UIImageView!
var overlayView = UIView()
var logoAppeared:Bool? = false
let labelLogo = UILabel()
override func viewDidLayoutSubviews() {
//move picture off screen
animateDidLayout()
}
override func viewDidAppear(_ animated: Bool) {
//move picture on screen and adjust view
animateDidAppear()
}
//animate the image before it appears on screen
func animateDidLayout(){
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidLayoutSubviews, in else")
return
}
print("appeared value after else in ViewDidLayoutSubvies \(appeared)")
//animate overlayView
if self.view.subviews.contains(overlayView) != true{
self.overlayView = UIView(frame: self.view.frame)
self.view.addSubview(self.overlayView)
}
self.overlayView.backgroundColor = UIColor.black
self.overlayView.layer.opacity = 0.4
self.overlayView.alpha = 0.4
//animate imageLogo
if self.view.subviews.contains(imageLogo) != true{
self.imageLogo = UIImageView(image:paymentLogo)
self.view.addSubview(imageLogo)
}
imageLogo.frame = CGRect(x: 0, y: 0, width: 100,
height: 100)
imageLogo.center.x -= 400
//animate labelLogo
self.labelLogo.frame =
CGRect(x: 0, y: 0, width: 200, height: 21)
self.labelLogo.center.x -= 400
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textAlignment = .center
if self.view.subviews.contains(labelLogo) != true{
self.view.addSubview(labelLogo)
}
}//end of animateDidLayout
//animate the logo when the view has appeared
//call it in ViewDidAppear
func animateDidAppear() {
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidAppear, in else")
return
}
print("appeared value in viewDidAppear after else \(appeared)")
UIView.animate(withDuration: 1.0, delay: 0.1, options: [],
animations: {
//animate overlayView
// self.overlayView = UIView(frame: self.view.frame)
//self.overlayView.backgroundColor = UIColor.black
//self.overlayView.alpha = 0.4
//animate labelLogo
self.labelLogo.frame = CGRect(x: self.view.center.x - 100,
y: 340, width: 200, height: 21)
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textColor = .white
self.labelLogo.textAlignment = .center
self.labelLogo.sizeToFit()
//animate imageLogo
self.imageLogo.frame =
CGRect(x: self.view.center.x - 50,y: 250,width: 100,height: 90)
}) { finished in
}
UIView.animate(withDuration: 0.5, delay: 5.0, options: .curveEaseInOut, animations: {
self.overlayView.alpha = 0
self.imageLogo.alpha = 0
self.labelLogo.alpha = 0
}, completion: {
finished in
self.overlayView.isHidden = true //it is hidden :)
self.imageLogo.isHidden = true
self.labelLogo.isHidden = true
self.logoAppeared = true
})
} //end of animateDidAppear}
If you prefer to wait 5 seconds and hide without animation you could use
let when = DispatchTime.now() + 5
DispatchQueue.main.asyncAfter(deadline: when) {// Your code with delay}
Or as a really fun alternative using your code and the delay
class ViewController: UIViewController {
var counter = 0
let paymentLogo = UIImage(named: "paymentImage")
var imageLogo:UIImageView!
var overlayView = UIView()
var logoAppeared:Bool? = false
let labelLogo = UILabel()
override func viewDidLayoutSubviews() {
//move picture off screen
animateDidLayout()
}
override func viewDidAppear(_ animated: Bool) {
//move picture on screen and adjust view
animateDidAppear()
}
//animate the image before it appears on screen
func animateDidLayout(){
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidLayoutSubviews, in else")
return
}
print("appeared value after else in ViewDidLayoutSubvies \(appeared)")
//animate overlayView
if self.view.subviews.contains(overlayView) != true{
self.overlayView = UIView(frame: self.view.frame)
self.view.addSubview(self.overlayView)
}
self.overlayView.backgroundColor = UIColor.black
self.overlayView.layer.opacity = 0.4
self.overlayView.alpha = 0.4
//animate imageLogo
if self.view.subviews.contains(imageLogo) != true{
self.imageLogo = UIImageView(image:paymentLogo)
self.view.addSubview(imageLogo)
}
imageLogo.frame = CGRect(x: 0, y: 0, width: 100,
height: 100)
imageLogo.center.x -= 400
//animate labelLogo
self.labelLogo.frame =
CGRect(x: 0, y: 0, width: 200, height: 21)
self.labelLogo.center.x -= 400
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textAlignment = .center
if self.view.subviews.contains(labelLogo) != true{
self.view.addSubview(labelLogo)
}
}//end of animateDidLayout
//animate the logo when the view has appeared
//call it in ViewDidAppear
func animateDidAppear() {
guard let appeared = self.logoAppeared, appeared == false else{
print("appeared is true in viewDidAppear, in else")
return
}
print("appeared value in viewDidAppear after else \(appeared)")
UIView.animate(withDuration: 1.0, delay: 0.1, options: [],
animations: {
//animate overlayView
// self.overlayView = UIView(frame: self.view.frame)
//self.overlayView.backgroundColor = UIColor.black
//self.overlayView.alpha = 0.4
//animate labelLogo
self.labelLogo.frame = CGRect(x: self.view.center.x - 100,
y: 340, width: 200, height: 21)
self.labelLogo.text = "Your booking is confirmed!"
self.labelLogo.textColor = .white
self.labelLogo.textAlignment = .center
self.labelLogo.sizeToFit()
//animate imageLogo
self.imageLogo.frame =
CGRect(x: self.view.center.x - 50,y: 250,width: 100,height: 90)
}) { finished in
}
let when = DispatchTime.now() + 5
DispatchQueue.main.asyncAfter(deadline: when) {
let transition = CATransition()
transition.duration = 0.5
transition.type = "suckEffect"
self.view.layer.add(transition, forKey: nil)
self.overlayView.isHidden = true //it is hidden :)
self.imageLogo.isHidden = true
self.labelLogo.isHidden = true
self.logoAppeared = true
}
} //end of animateDidAppear}