Im using Lottie animation in my app and im trying to keep the animation running in the background when i exit the app and open it again (not force close) ..
I was able to do so successfully, but the problem is the animation stops when i select different tab bar item and go back to the tab bar item that has the animation view.
this is my code.
import UIKit
import Lottie
import UserNotifications
import NotificationCenter
class HomeViewController: UIViewController {
#IBOutlet weak var animationView: UIView!
var animation : AnimationView?
override func viewDidLoad() {
super.viewDidLoad()
setupAnimation()
NotificationCenter.default.addObserver(self, selector: #selector(applicationEnterInForground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
func setupAnimation() {
animation = AnimationView(name: "cong")
animation?.frame = self.animationView.bounds
self.animationView.addSubview(animation!)
animation?.loopMode = .loop
animation?.contentMode = .scaleAspectFit
animation?.play()
}
#objc func applicationEnterInForground() {
if animation != nil {
if !(self.animation?.isAnimationPlaying)! {self.animation?.play()}}
}
}
Swift 5
There is a property, that can be set & it will restore your Lottie animation:
yourAnimationView.backgroundBehavior = .pauseAndRestore
By default, this property is set to .pause
Better, use viewWillAppear/viewDidAppear to start the animation again and remove observing the willEnterForegroundNotification.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if self.animation?.isAnimationPlaying == false {
self.animation?.play()
}
}
Related
I am working on a app with a tab bar with four separate tabs. I for example save a number that can be changed/modified in three of those tabs. A label, that displays that number is included in all four of those tabs. However, when I change the number in one tab, the labels of the other tabs are not updated when I switch tabs.
I tried including this in each viewDidLoad() of the view controllers of the tabs:
self.tabBarController?.delegate = self
and then used:
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let tabBarIndex = tabBarController.selectedIndex
if tabBarIndex == 2{
updateLabel()
}
}
If I do that in all viewControllers and select the tabs, the view is still changed, but the tabBarController fails, so that the function updateLabel() isn't called at all.
If I only include the code in the First View Controller and expand this part:
if tabBarIndex == 2{
updateLabel()
}
to cover all tabs, the respective functions (updateLabel()) of the classes are called but the Label itself is nil.
#IBOutlet weak var HoursLabel: UILabel!
func updateLabel(){
if HoursLabel != nil{
//code
}
}
And the label isn't updated.
Does someone know how to fix this? Thank you so much in advance :)
hey i got some solutions for you hope this is what you want.
i'm updating your tab label value with Notification Center here is some code
// TabbarController Code
import UIKit
class TabbarViewController: UITabBarController, UITabBarControllerDelegate {
//MARK Life View Cycle
override func viewDidLoad() {
super.viewDidLoad()
tabBarController?.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(self.TabbarNoitifuntionCall), name: NSNotification.Name(rawValue: "CallTabBarNotificationsCenter"), object: nil) // this code will call when ever you update your value in view controller
}
//MARK:- Private Functions
#objc func TabbarNoitifuntionCall(_ notification: Notification) {
self.viewControllers![0].title = "First " + String(notification.object as! Int)
self.viewControllers![1].title = "Second " + String(notification.object as! Int)
}
}
// First Tabbar Controller
import UIKit
class FirstVc: UIViewController {
//MARK:- IBOutlet
#IBOutlet weak var update_lbl: UILabel!
//MARK:- Variables
var count = Int()
//MARK:- Life View Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK:- Private Function
#IBAction func buttonAction(_ sender: UIButton) {
count = count + 1
update_lbl.text = String(count)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CallTabBarNotificationsCenter"), object: count) // here we will call notifications center so our labal value upadate
}
}
// Second Tabbar Controller
import UIKit
class SecondVc: UIViewController {
//MARK:- IBOutlet
#IBOutlet weak var update_lbll: UILabel!
//MARK:- Variables
var count = Int()
//MARK:- Life View Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK:- Private Function
#IBAction func button_action(_ sender: Any) {
count = count + 1
update_lbll.text = String(count)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CallTabBarNotificationsCenter"), object: count) // here we will call notifications center so our labal value upadate
}
}
i hope this is the simple way if anyone add something then please go head
Thank you.
I am trying to display an UIImageView when a button is pressed. In my main story board, I have an ImageView(hidden) and an UIButton. How do I modify the ViewController to make that happen?
import UIKit
class ViewController: UIViewController {
#IBOutlet var ImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
ImageView.image = UIImage(named: "18.pic_hd.jpg")
}
}
This is what I currently have so far, but the program breaks and gives me Thread 1: signal SIGABRT. I am new to Xcode and Swift, so any direction is appreciated!
You should drag and drop UIButton from storyBoard to your code and use Action to have an IBAction in your viewController.
After that use imageView.isHidden = false to show the image and vice versa.
sample code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var imageView: UIImageView!
#IBAction func someButton(_ sender: UIButton) {
// when button tapped this code will execute
imageView.isHidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
imageView.isHidden = true
}
}
use
ImageView.isHidden = true
to hide your image, and
ImageView.isHidden = false
to show it.
add an IBAction to your button to do this.
I have a UITableViewController that is embedded in a UINavigationController. When I click on a row I am attempting to upload a file. To show the progress of this upload I have decided to use custom popup (another UIViewController) - if anyone has a better idea to show the progress of the upload in this context I am open to it.
The only idea I have to transfer continuous data from one UIViewController to another (if that is possible) is by using a Singleton. My code is below, my issue at the moment is I do not know how to update the progress view even though now it has access to the progress data via the singleton.
class SharedSingleton{
private init(){}
static let shared = SharedSingleton()
var prog: Float = 0
}
UITableViewController:
Using Alamofire to get the fraction of upload completed:
/**TRACK PROGRESS OF UPLOAD**/
upload.uploadProgress { progress in
//print(progress.fractionCompleted)
let mySingleton = SharedSingleton.shared
mySingleton.prog = Float(progress.fractionCompleted)
print("mySingleton.prog: \(mySingleton.prog)")
UIViewController containing popup:
#IBOutlet weak var popUpContainer: UIView!
#IBOutlet weak var uploadStatus: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
// Make popup have rounded corners
popUpContainer.layer.cornerRadius = 5
popUpContainer.layer.masksToBounds = true
// Call Singleton and assign progress of upload to progress view
// HOW TO UPDATE ??????
let mySingleton = SharedSingleton.shared
progressBar.progress = mySingleton.prog
}
One option would be to use NotificationCenter and in your pop-up view controller subscribe to notifications and in your API callback for the progress, publish a notification.
For example:
UploadNotifications.swift:
import Foundation
extension Notification.Name {
static let UploadProgress = Notification.Name("UploadProgress")
}
UploadProgressViewController.swift (your pop-up):
import UIKit
class UploadProgressViewController: UIViewController {
#IBOutlet weak var progressBar: UIProgressView!
private let progress: Progress = {
let progress = Progress()
progress.completedUnitCount = 0
progress.totalUnitCount = 100
return progress
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(self.uploadDidProgress(_:)), name: .UploadProgress, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
#objc private func uploadDidProgress(_ notification: Notification) {
if let progress = notification.object as? Int64 {
self.progress.completedUnitCount = progress
if progress == 100 {
// dismiss/exit
}
}
}
}
Then in your method with the upload progress callback:
upload.uploadProgress { progress in
NotificationCenter.default.post(name: .SyncDidProgress, object: Int64(progress))
}
I have a UIViewController (Main Menu) that is displayed after my other UIViewController (Loading Screen) finishes downloading/syncing data from the web. My Main Menu is having problems as it doesn't always display all the UIButtons that are on the view when it shows up! There is an inconsistancy, 1 out of every 10 times the Main Menu loads, all the UIButtons will appear.
Here's how the view should look:
Here's how the view usually shows up:
I can put my finger where the UIButtons should be and move my finger away and they'll appear. I can also tap where they should be and my segues will still trigger, but the UIButtons dont just automatically show up. It looks like
I attempted to add a MainMenuView.setNeedsDisplay() to the ViewDidLoad function and it didn't help. I also created a test UIButton on the view that triggers a MainMenuView.setNeedsDisplay() command but the hidden UIButtons remain hidden.
If I leave the screen idle for 30 or so seconds, all the UIButtons will randomly appear without me having to manually make them appear.
The Main Menu view is normal and all UIButtons are visible if I segue to it from any part of the app aside from my Loading Screen.
Edit: Main Menu Code - (references are Strong)
import UIKit
import CoreData
class MainMenuViewController: UIViewController {
// MARK: References
#IBOutlet var btnGasManifolds: UIButton!
#IBOutlet var btnAirCompressors: UIButton!
#IBOutlet var btnVacuumPumps: UIButton!
#IBOutlet var btnUnitConversion: UIButton!
#IBOutlet var btnCFMCalculator: UIButton!
#IBOutlet var mainMenuView: UIView!
var userData = [NSManagedObject]()
// MARK: Functions
override func viewDidLoad() {
var name = String()
for duserData in userData {
name = duserData.value(forKey: "nameFull") as! String
}
print("Main Menu\n->\(name)")
backgroundSetup()
}
override func viewDidAppear(_ animated: Bool) {
mainMenuView.setNeedsDisplay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnTest(_ sender: Any) {
mainMenuView.setNeedsDisplay()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any!) {
if segue.identifier == "settingsSegue" {
let destination = segue.destination as! SettingsViewController
destination.userData = userData
}
}
// Background Setup
func backgroundSetup() {
let background = UIImage(named: "Data Screens")
var imageView : UIImageView!
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = UIViewContentMode.scaleAspectFill
imageView.clipsToBounds = true
imageView.image = background
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
}
}
The code which creates and shows the buttons after fetching the data from server needs to run on Main UI thread. If the code is running the background thread it will not properly display the UI elements and will take some time or manual scroll before showing the controls.
Run the code on Dispatch main queue.
dispatch_async(dispatch_get_main_queue(),{
//do some work
})
OR
Override one of the methods from ViewWillLayoutSubviews and ViewDidLayoutSubviews accordingly and run your code in these methods.
I have my app with a custom splash screen to load some data from internet. In iOS 8 I can see this ViewController, but in iOS9 I only see it in the first launch of the app the rest of the launches iphone pauses on springboard and then shows the list of data that should be visible after the custom splash screen.
I don't know if there's some bug with ios9 related to this topic :(
Here's is my code, hope anyone can help me.
class SplashScreenVC: UIViewController {
#IBOutlet weak var spinner: UIActivityIndicatorView!
#IBOutlet weak var splashImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "rotated", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
func rotated() {
if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation)) {
splashImageView.image = UIImage(named:"eva_splash_landscape_")
}
if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)) {
splashImageView.image = UIImage(named:"eva_splash_portrait_")
}
}
func startActivityIndicator() {
self.spinner.activityIndicatorViewStyle = .WhiteLarge
self.spinner.center = self.view.center
self.spinner.hidesWhenStopped = true
self.spinner.frame.size.height = 50
self.spinner.frame.size.width = 50
self.parentViewController?.view.addSubview(spinner)
self.spinner.startAnimating()
}
}
Sounds like your Storyboard files could be disconnect from your build target. Make sure Main Interface is your Main.Storyboard file and Launch Screen File is your Custom storyboard file