Loading string from plist swift - swift

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

Update label when returning from background

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)")
}

Get just the x value from iOS Accelerometer data

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)
}
}

i want an animation view when the game ends. and my animationView will appear first then next is congratulationview animated.?

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

Adding items to NSArrayController causes EXC_BAD_INSTRUCTION

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.

Image appear when timer is at 1

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")
})
}
}