I have a problem trying to update the label when the app returns from Background. I already implemented LocalNotifications for my timer app and is working perfect but when I return to the app the countdown label is stopped.
So basically I am trying to find the way to update the countdown label with the current time left. I would appreciate any help!
My Code is here:
var timer = Timer()
var teas = Teas()
var isTimerRunning = false
var alarmSound = AVAudioPlayer()
var playing = false
var initialValueOfTime = 0
var timeDuration = 0
var currentBackgroundDate = Date()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(teasGoBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(runTimer), name: UIApplication.didBecomeActiveNotification, object: nil)
}
#objc func runTimer() {
if isTimerRunning {
teas.time -= 1
let difference = Date().timeIntervalSince(self.currentBackgroundDate)
timeDuration = timeDuration + Int(difference)
if teas.time <= 0 {
timer.invalidate()
startButton.setTitle("Done", for: .normal)
}
}
else {
teas.time = initialValueOfTime
}
#objc func resetTimer() {
timer.invalidate()
runTimer()
}
#objc func teasGoBackground() {
timer.invalidate()
currentBackgroundDate = Date()
}
#IBAction func startButtonPressed(_ sender: Any) {
if !isTimerRunning {
navigationItem.hidesBackButton = true
isTimerRunning = true
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(runTimer), userInfo: nil, repeats: true)
print("time")
startButton.setTitle("Stop Brewing", for: .normal)
} else {
navigationItem.hidesBackButton = false
isTimerRunning = false
resetTimer()
startButton.setTitle("Start Brewing", for: .normal)
}
}
You need to add your observers inside viewDidLoad(), NOT in viewDidAppear
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(teasGoBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(runTimer), name: UIApplication.didBecomeActiveNotification, object: nil)
}
Finally I implemented this code to my project and worked!
if let date = UserDefaults.standard.object(forKey: "teastart\(teas.id)") as? Date {
let now = Date()
let secondsTillNow = now.timeIntervalSince1970
let previousSeconds = date.timeIntervalSince1970
let timeSinceStart = secondsTillNow - previousSeconds
let time = Int(timeSinceStart)
if time > teas.time {
initialValueOfTime = teas.time
startButton.setTitle(NSLocalizedString("Start Brewing", comment: ""), for: .normal)
UserDefaults.standard.set(false, forKey: "timerunning\(teas.id)")
} else {
initialValueOfTime = teas.time - time
startButton.setTitle(NSLocalizedString("Stop Brewing", comment: ""), for: .normal)
UserDefaults.standard.set(true, forKey: "timerunning\(teas.id)")
}
} else {
initialValueOfTime = teas.time
UserDefaults.standard.set(false, forKey: "timerunning\(teas.id)")
}
Related
I'm quite new to this and really enjoying swift, I have managed to work must stuff out but this has me stumped. I want to get just the x value (a double) from my accelerometer data.
The below pulls the data and prints out :x 0.476379 y -0.849365 z -0.041885 # 568028.476360
This is great, but I just want :0.476379 - any ideas?
class ViewController: UIViewController {
#objc func update() {
if let accelerometerData = motionManager.accelerometerData {
print(accelerometerData)
}
}
let motionManager = CMMotionManager()
var timer: Timer!
override func viewDidLoad()
{
super.viewDidLoad()
motionManager.startAccelerometerUpdates()
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true)
}
SwiftUI
let accelTuple = (acceleration.x)
import Foundation
import CoreMotion
class Motion {
var motion = CMMotionManager()
#Published var timer = Timer()
private var motionManager = CMMotionManager()
func startAccelerometer() {
if motion.isAccelerometerAvailable {
self.motion.accelerometerUpdateInterval = 5
motion.startAccelerometerUpdates()
self.timer = Timer(fire: Date(), interval: (10),
repeats: true, block: { (timer) in
if let data = self.motion.accelerometerData {
let acceleration = data.acceleration
self.accelerometerData = ("Accelerometer data : \(data)")
print(self.accelerometerData)
let accelTuple = (acceleration.x, acceleration.y, acceleration.z)
valuesArray.append(accelTuple)
}
})
RunLoop.current.add(timer, forMode: .default)
}
}
func startGyroscope() {
if motion.isGyroAvailable {
self.motion.gyroUpdateInterval = 5
motion.startGyroUpdates()
self.timer = Timer(fire: Date(), interval: (10),
repeats: true, block: { (timer) in
if let data = self.motion.gyroData {
let x = data.rotationRate.x
let y = data.rotationRate.y
let z = data.rotationRate.z
self.gyroscopeData = ("Gyroscope data : \(data)")
print(self.gyroscopeData)
let gyroTuple = (x, y, z)
valuesArray.append(gyroTuple)
}
})
RunLoop.current.add(timer, forMode: .default)
}
}
func startMagnetometer() {
if motion.isMagnetometerAvailable {
self.motion.magnetometerUpdateInterval = 5
motion.startMagnetometerUpdates()
self.timer = Timer(fire: Date(), interval: (10),
repeats: true, block: { (timer) in
if let data = self.motion.magnetometerData {
let acceleration = data.magneticField
self.magnetometerData = ("Magnetometer data : \(data)")
print(self.magnetometerData)
let magneTuple = (acceleration.x, acceleration.y, acceleration.z)
valuesArray.append(magneTuple)
}
})
RunLoop.current.add(timer, forMode: .default)
}
}
}
Working code thanks to Nick:
class ViewController: UIViewController {
#objc func update() {
if let accelerometerData = motionManager.accelerometerData?.acceleration.x {
print(accelerometerData)
}
}
pic of database
I am trying to show a label with the user's status on their profile page. after logging in the user gets presented with a VC that has a side menu. on that side menu is a "profile" option. once choosing this they go to their profile controller. right now i simply need to search users/current uid/ "MembershipStatus" and present this result into a label called "welcomeLabel".
I am returning nul
import UIKit
import Firebase
class NonMemberProfileController: UIViewController {
// MARK: - Properties
var welcomeLabel: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 28)
label.translatesAutoresizingMaskIntoConstraints = false
label.alpha = 0
return label
}()
// MARK: - Init
override func viewDidLoad()
{
super.viewDidLoad()
authenticateUserAndConfigureView()
}
func loadUserData()
{
guard let uid = Auth.auth().currentUser?.uid else {return}
//.child("MembershipStatus")
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value) {
(snapshot) in
if snapshot.hasChild("MembershipStatus"){
print("true we have bingo")
} else {
print("no bueno")
dump(snapshot)
}
guard let status = snapshot.value as? String else { return }
self.welcomeLabel.text = "Welcome, \(status)"
print("this is lkjfdskjklsfad" + status)
UIView.animate(withDuration: 0.5, animations: {
self.welcomeLabel.alpha = 1
})
}
}
func authenticateUserAndConfigureView(){
if Auth.auth().currentUser == nil {
DispatchQueue.main.async {
let navController = UINavigationController(rootViewController: LoginViewController())
navController.navigationBar.barStyle = .black
self.present(navController, animated: true, completion: nil)
}
} else {
configureNavigationBar()
loadUserData()
}
}
// MARK: - Selectors
#objc func handleDismiss() {
dismiss(animated: true, completion: nil)
}
// MARK: - Helper Functions
func configureNavigationBar() {
view.backgroundColor = UIColor.lightGray
navigationItem.title = "Profile"
navigationController?.navigationBar.barTintColor = .darkGray
navigationController?.navigationBar.barStyle = .black
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "Home_2x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleDismiss))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "baseline_settings_white_24dp").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleDismiss))
view.addSubview(welcomeLabel)
welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
welcomeLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
You are using Cloud Firestore for data storage but your code is reading data form RealTime Database. You have to read data like this:
let userRef = Firestore.firestore().collection("users").document(uid)
userRef.getDocument { (documentSnapshot, error) in guard
let document = documentSnapshot?.data() else {
print(error)
return
}
print(document)
}
this is my code thank you can someone know how to do that?
this scene is when the the game is over
func prepareTimeCount() {
self.timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(self.timeCount),
userInfo: nil,
repeats: true)
}
func prepareWinView() {
let images:NSMutableArray! = NSMutableArray()
for i in 1...12
{
let image = UIImage(named:"animationView\(i).png")
images.add(image!)
}
self.congratulationView.animationImages = images as [AnyObject] as? [UIImage]
self.congratulationView.animationDuration = 3
self.congratulationView.startAnimating()
self.view.addSubview(self.congratulationView)
}
#objc func timeCount() {
var timeCount = Int(self.timeCountLabel!.text!) ?? 0
if(timeCount <= 0 ) {
self.timer.invalidate()
self.gameOver()
} else {
timeCount-=1
}
self.timeCountLabel.text = String(timeCount)
}
func gameOver() {
self.isGameOver = true
self.birdView.stopAnimating()
self.timer.invalidate()
}
and here is the codes when the game ends
func gameWin() {
let defaults = UserDefaults.standard
defaults.setValue("\(self.levelNomber)", forKey: "level")
self.txtMessageTitle.text = "Congratulations"
self.txtMessageSubTitle.text = "You won the game"
self.isGameOver = true
self.birdView.stopAnimating()
viewMessage.isHidden = false
congratulationView.isHidden = false
self.timer.invalidate()
}
can someone help me solve this error?
i want the the animation will see first before the congratulation messages appear. thank you
my requirement is i have horizontal scroll view in second half of the screen in that second half i am loading xib as a swipe layout and my first half i have bar code reader.click here for image
if user user click on scan button camera will and it will scan the bar code and get output if user in the first view in scroll then scaned value should be in first xibs textview and the code is
import UIKit
import Alamofire
import AVFoundation
class sgstockallocationserialnumberViewController: SGBaseViewController,UIScrollViewDelegate,AVCaptureMetadataOutputObjectsDelegate {
#IBOutlet weak var serialnumberprocessezsorcancelview: UIView!
#IBOutlet weak var txtseialnumbers: UITextView!
#IBOutlet weak var clientview: UIView!
#IBOutlet weak var scroll_horizontal: UIScrollView!
#IBOutlet weak var serialinternalview: UIView!
#IBOutlet weak var cameraview: UIView!
var featureArray = [Dictionary<String,String>]()
var stockList: [Parameters] = []
var captureSession: AVCaptureSession!
var previewLayer: AVCaptureVideoPreviewLayer!
var output = AVCaptureMetadataOutput()
var orderlines: sgpurchaseorderorderlinewithmsg?
var arrayofcode:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
serialnumberprocessezsorcancelview.layer.cornerRadius = 5
serialnumberprocessezsorcancelview.layer.shadowColor = UIColor.gray.cgColor
serialnumberprocessezsorcancelview.layer.shadowOffset = CGSize(width: 2, height: 2)
serialnumberprocessezsorcancelview.layer.shadowRadius = 5
serialnumberprocessezsorcancelview.layer.shadowOpacity = 1.0
clientview.layer.cornerRadius = 5
print(scroll_horizontal.contentSize)
scroll_horizontal.showsHorizontalScrollIndicator = false
scroll_horizontal.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(sgstockallocationserialnumberViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
if SGManager.sharedManager.getorderlines()?.data != nil{
let modeldata = SGManager.sharedManager.getorderlines()
self.orderlines = modeldata
for i in 0...(orderlines?.data.count)! - 1 {
let cell_details =
["title":self.orderlines?.data[i].productName,"Quantity":String(describing:self.orderlines!.data[i].quantity!)] as [String : Any]
featureArray.append(cell_details as! [String : String])
}
let cell_details = ["title":"Miscellaneous","Quantity":""]
featureArray.append(cell_details )
}
}
override func viewDidAppear(_ animated: Bool) {
scroll_horizontal.isPagingEnabled = true
scroll_horizontal.contentSize = CGSize(width: self.serialinternalview.frame.size.width * CGFloat(featureArray.count), height: 188)
self.loadFeatures()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
func dismissKeyboard() {
view.endEditing(true)
}
func loadFeatures() {
for (index, feature) in featureArray.enumerated() {
if let featureView = Bundle.main.loadNibNamed("Feature", owner: self, options: nil)?.first as? FeatureView {
featureView.seraialnumbertextareaview.layer.borderColor = UIColor.UIColorFromRGB(fromHex: 0xD6D6D6).cgColor
featureView.seraialnumbertextareaview.layer.borderWidth = 1
featureView.internalview_xib.layer.borderColor = UIColor.UIColorFromRGB(fromHex: 0xD6D6D6).cgColor
featureView.internalview_xib.layer.borderWidth = 1
featureView.internalview_xib.layer.cornerRadius = 5
featureView.internalview_xib.layer.masksToBounds = true
featureView.seraialnumbertextareaview.layer.cornerRadius = 5
featureView.seraialnumbertextareaview.layer.masksToBounds = true
featureView.lblnetworkname.text = feature["title"]
featureView.lblquantity_xib.text = feature["Quantity"]
var textview_ = ""
featureView.tag = index
scroll_horizontal.addSubview(featureView)
featureView.frame.size.width = self.serialinternalview.frame.width
featureView.frame.origin.x = CGFloat(index) * self.serialinternalview.frame.size.width
print(featureView.frame.origin.x)
print(self.serialinternalview.bounds.size.width)
}
}
}
func buyFeature (sender:UIButton) {
print("The user wants to buy feature \(sender.tag)")
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x / scrollView.frame.size.width
// print(Int(page))
// featurePageControl.currentPage = Int(page)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func process(_ sender: UIButton) {
if txtseialnumbers.text != ""{
getnewpurchaseorderfiltermanufacturer()
}
else {
let alert = UIAlertController(title: "No serial numbers detected", message:"add the serial numbers", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
#IBAction func cancel(_ sender: UIButton) {
}
func getnewpurchaseorderfiltermanufacturer(){
stockList.removeAll()
let stocklistintrernal : Parameters = [
"productid" :0,
"productCategoryId" : 1, "productParameterValue": txtseialnumbers.text]
print(txtseialnumbers.text)
stockList.append(stocklistintrernal)
UserDefaults.standard.setValue(txtseialnumbers.text, forKey: "serialnumbers")
let clientid_stockallocation = UserDefaults.standard.object(forKey: "clientidfromstockallocation")
let params: [String : Any] = ["productParameterValue" :stockList,"isCommit":"False","toClientId":clientid_stockallocation]
SGWebServices.sharedWebServices.stockalloction(params:params) { (error, response) in
if (error == nil) {
var purchaseordermanufacturer:sgstockallocationwhenserialnumberpassed?
purchaseordermanufacturer = response
// print(purchaseordermanufacturer?.message)
if purchaseordermanufacturer?.message == "Success"
{
let userDefaults = UserDefaults.standard
let encodedData = NSKeyedArchiver.archivedData(withRootObject: response!)
userDefaults.set(encodedData, forKey: "summary")
userDefaults.synchronize()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "SGStockallocationsummaryViewController")
UserDefaults.standard.set(self.stockList, forKey: "stoclist")
self.present(controller, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "", message: purchaseordermanufacturer?.message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// print("success")
}
else{
let alert = UIAlertController(title: "!", message: String(describing: error), preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}}}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if (captureSession?.isRunning == false) {
captureSession.startRunning();
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if (captureSession?.isRunning == true) {
captureSession.stopRunning();
}
}
#IBAction func scanstarted(_ sender: UIButton) {
barcodereaderon()
}
#IBAction func scanstop(_ sender: UIButton) {
stopsession()
print(arrayofcode.count)
}
func barcodereaderon(){
// view.backgroundColor = UIColor.black
captureSession = AVCaptureSession()
let videoCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed();
return;
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeAztecCode]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.frame = cameraview.layer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
cameraview.layer.addSublayer(previewLayer)
captureSession.startRunning();
}
func stopsession(){
captureSession.stopRunning()
cameraview.backgroundColor = UIColor.black
previewLayer.removeFromSuperlayer()
}
func failed() {
let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
captureSession = nil
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
// captureSession.stopRunning()
if let metadataObject = metadataObjects.first {
let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
// dismiss(animated: true)
found(code: readableObject.stringValue);
}
}
func found(code: String) {
if arrayofcode.contains(code) {
}
else{
let page = scroll_horizontal.contentOffset.x / scroll_horizontal.frame.size.width
print(page)
var featureView = Bundle.main.loadNibNamed("Feature", owner: self, options: nil)?.first as? FeatureView
// featureView?.tag = Int(page)
// var tmpButton = featureView?.viewWithTag(Int(page)) as? tea
print(Int(page))
featureView = featureView?.viewWithTag(Int(page)) as! FeatureView?
featureView?.textarea_xib.text = code
print(featureView?.textarea_xib.text!)
arrayofcode.append(code)
var barcodeinarraay:[String] = []
arrayofcode.append(code)
}
// UserDefaults.standard.set(code, forKey: "code")
// UserDefaults.standard.synchronize()
print(code)
// arrayofcode.append(code)
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// let controller = storyboard.instantiateViewController(withIdentifier: "screenViewController")
// self.present(controller, animated: true, completion: nil)
//
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}
I am trying to load a string from plist with the code below, then i want to use it in typewriter animation. But I failed to convert the string into the array. How should I convert it?
The line var myText = Array(Data[0].characters) gives error.
class ViewController: UIViewController {
var Data = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let word = NSBundle.mainBundle().pathForResource("Chapter 1", ofType: "plist")
let dict = NSDictionary(contentsOfFile: word!)
Data = dict!.objectForKey("Chapter 1") as! [String]
}
#IBOutlet weak var myTypeWriter: UILabel!
var myText = Array(Data[0].characters)
var myCounter = 0
var timer:NSTimer?
func fireTimer(){
timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(ViewController.typeLetter), userInfo: nil, repeats: true)
}
func typeLetter(){
if myCounter < myText.count {
myTypeWriter.text = myTypeWriter.text! + String(myText[myCounter])
let randomInterval = Double((arc4random_uniform(8)+1))/100
timer?.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(randomInterval, target: self, selector: #selector(ViewController.typeLetter), userInfo: nil, repeats: false)
} else {
timer?.invalidate()
}
myCounter += 1
}