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
}
Related
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)")
}
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)
}
}
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
I've had the same problem for a few days now and it's been killing me. Whenever I run my script, I get a EXC_BAD_INSTRUCTION. It happens when I add an array of objects to an NSArrayController, bount to an NSTableView. Below is my code:
AppDelegate.swift:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
#IBOutlet weak var mainTabView: NSTabView!
#IBOutlet weak var tracksAC: NSArrayController!
#IBOutlet weak var albumsAC: NSArrayController!
func checkIfFileExists(atPath path: String, isDirectory: Bool = false, createIfNeeded createNew: Bool = false) -> Int {
var isDir: ObjCBool = ObjCBool(isDirectory)
if !FileManager.default.fileExists(atPath: path, isDirectory: &isDir) {
if createNew {
do {
if isDirectory {
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true)
}else{
FileManager.default.createFile(atPath: path, contents: nil)
}
return 2
}catch{
return 3
}
}else{
return 0
}
}
return 1
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
//Create application support folder if it's not existent and populate with all needed files
let paths = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)
let appSupportDir = paths[0] + "/Project Alpha"
//Create application folder if needed
let folderStatus = checkIfFileExists(atPath: appSupportDir, isDirectory: true, createIfNeeded: true)
if folderStatus == 1 || folderStatus == 2 {
_ = checkIfFileExists(atPath: appSupportDir + "/Songs.txt", createIfNeeded: true)
_ = checkIfFileExists(atPath: appSupportDir + "/Albums.txt", createIfNeeded: true)
_ = checkIfFileExists(atPath: appSupportDir + "/Genres.txt", createIfNeeded: true)
}
//Populate tracks table view
let tracks = getTracks()
print(tracks[0].name)
tracksAC.add(contentsOf: tracks) //This is where the error occures every time
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
#IBAction func openAlbumsTab(_ sender: NSToolbarItem) {
mainTabView.selectTabViewItem(at: 1)
}
}
Classes.swift:
import Cocoa
class Track: NSObject {
func getLine() -> String? {
let songsFilePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)[0] + "/Project Alpha/Songs.txt"
do {
let content = try String(contentsOfFile: songsFilePath)
let lines = content.components(separatedBy: "---===---")
let line = lines.first(where: {$0.hasPrefix(String(self.identifier) + ";")})
return line
}catch{
return nil
}
}
var identifier: Int
var name: String
var artist: String
var album: String
var genre: String
var vocals: String
var trackNumber: Int
init(line: String) {
let items = line.components(separatedBy: ";")
print(items)
self.identifier = Int(items[0])!
self.name = String(items[1])
self.artist = String(items[2])
self.genre = String(items[3])
self.vocals = String(items[4])
self.album = String(items[5])
self.trackNumber = Int(items[6])!
}
}
I have checked the getTracks function and normally it does return a list of Track objects, so I really don't know what's causing the error. The columns are bound to the array controller as shown via the link below:
screenshot
Any help would be greatly appreciated. Thanks in advance.
im making a reaction time app, and I have a label set to count with Seconds. I want to make my image appear when the label is at 1 second, but it doesn't appear. The timer works fine, just the image. Help me in swift please.
import UIKit
class timerViewController: UIViewController {
var go = NSTimeInterval()
var timer = NSTimer()
#IBOutlet weak var tapStop: UIImageView!
#IBOutlet weak var displayTimer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if displayTimer.text == "00:01:00"{
tapStop.image = UIImage(named: "carcrash")
}
}
#IBAction func stop(sender: UIButton) {
timer.invalidate()
}
#IBAction func start(sender: UIButton) {
if (!timer.valid) {
let test:Selector = "updateTime"
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: test, userInfo: nil, repeats: true)
go = NSDate.timeIntervalSinceReferenceDate()
}
}
func updateTime(){
var timeNow = NSDate.timeIntervalSinceReferenceDate()
var pass: NSTimeInterval = timeNow - go
let minutes1 = UInt8(pass / 60.0)
pass -= (NSTimeInterval(minutes1) * 60)
let seconds1 = UInt8(pass)
pass -= NSTimeInterval(seconds1)
let milli1 = UInt8(pass * 100)
let minutes2 = String(format: "%02d", minutes1)
let seconds2 = String(format: "%02d", seconds1)
let milli2 = String(format: "%02d", milli1)
displayTimer!.text = "\(minutes2):\(seconds2):\(milli2)"
}
}
You should put this:
if displayTimer.text == "00:01:00"{
tapStop.image = UIImage(named: "carcrash")
}
in your func updateTime() instead of viewDidLoad(), and put them into main thread, so that your image will be updated on the UI. Your func updateTime() will look like this:
func updateTime(){
var timeNow = NSDate.timeIntervalSinceReferenceDate()
var pass: NSTimeInterval = timeNow - go
let minutes1 = UInt8(pass / 60.0)
pass -= (NSTimeInterval(minutes1) * 60)
let seconds1 = UInt8(pass)
pass -= NSTimeInterval(seconds1)
let milli1 = UInt8(pass * 100)
let minutes2 = String(format: "%02d", minutes1)
let seconds2 = String(format: "%02d", seconds1)
let milli2 = String(format: "%02d", milli1)
displayTimer!.text = "\(minutes2):\(seconds2):\(milli2)"
if displayTimer.text == "00:01:00"{
dispatch_async(dispatch_get_main_queue(),{
tapStop.image = UIImage(named: "carcrash")
})
}
}