Use of unresolved identifier userDefaults - ios

What is causing this to happen? the two instances of this error apear at the very bottom of my view controller in which the lines start with "userDefaults". here is my code
import UIKit
class SecondViewController : UIViewController,UITextFieldDelegate {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var datePicker: UIDatePicker!
var aRandomDate = NSDate()
override func viewDidLoad() {
super.viewDidLoad()
datePicker.addTarget(self, action: Selector("datePickerChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerChanged(datePicker:UIDatePicker) {
var dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
var strDate = dateFormatter.stringFromDate(datePicker.date)
dateLabel.text = strDate
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
#IBAction func Save(sender: UIButton) {
var t = EventSaver(pEventName: "Drinking Coffee", pEventDate: aRandomDate )
let encodedEventName = NSKeyedArchiver.archivedDataWithRootObject(t.EventName)
let encodedEventDate = NSKeyedArchiver.archivedDataWithRootObject(t.EventDate)
var encodedArray: [NSData] = [encodedEventName,]
userDefaults.setObject(encodedArray, forKey: "Event")
userDefaults.synchronize()
println("saved")
}
}

Make it like this:
#IBAction func Save(sender: UIButton) {
var t = EventSaver(pEventName: "Drinking Coffee", pEventDate: aRandomDate )
var userDefaults = NSUserDefaults.standardUserDefaults()
let encodedEventName = NSKeyedArchiver.archivedDataWithRootObject(t.EventName)
let encodedEventDate = NSKeyedArchiver.archivedDataWithRootObject(t.EventDate)
var encodedArray: [NSData] = [encodedEventName,]
userDefaults.setObject(encodedArray, forKey: "Event")
userDefaults.synchronize()
println("saved")
}

It seems like you haven't declared the constant userDefaults.
Add the following line before you set the encodedArray object in the userDefaults:
let userDefaults = NSUserDefaults.standardUserDefaults()

You aren't declaring userDefauts
let userDefaults = NSUserDefaults.standardUserDefaults()

Related

How to add mutiple progress views to a timer?

here is all of the code that I am using for this project. I have four progress views and when the first end an alarm goes off and then the next start eminently and then goes to the next and then to the fourth one where the timer ends after that and the timer goes off one more time and then the timers stop.
import UIKit
import AVFoundation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btnPressed4(_ sender: Any) {
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.timeStyle = .short
let dateTimeString = formatter.string(from: currentDateTime)
timePrint4.text = dateTimeString
btnPressed4.titleLabel?.textColor = UIColor.white
}
#IBAction func btnPressed3(_ sender: Any) {
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.timeStyle = .short
let dateTimeString = formatter.string(from: currentDateTime)
timePrint3.text = dateTimeString
btnPressed3.titleLabel?.textColor = UIColor.white
}
#IBAction func btnPressed2(_ sender: UIButton) {
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.timeStyle = .short
let dateTimeString = formatter.string(from: currentDateTime)
timePrint2.text = dateTimeString
btnPressed2.titleLabel?.textColor = UIColor.green
}
#IBAction func btnPressed1(_ sender: UIButton) {
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.timeStyle = .short
let dateTimeString = formatter.string(from: currentDateTime)
timePrint1.text = dateTimeString
}
#IBOutlet weak var btnPressed1: UIButton!
#IBOutlet weak var btnPressed2: UIButton!
#IBOutlet weak var btnPressed3: UIButton!
#IBOutlet weak var btnPressed4: UIButton!
#IBOutlet weak var timePrint1: UILabel!
#IBOutlet weak var timePrint2: UILabel!
#IBOutlet weak var timePrint4: UILabel!
#IBOutlet weak var timePrint3: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var progressBar1: UIProgressView!
#IBOutlet weak var progressBar2: UIProgressView!
#IBOutlet weak var progressBar3: UIProgressView!
#IBOutlet weak var progressBar4: UIProgressView!
let start = 5
var timer = Timer()
var player: AVAudioPlayer!
var totalTime = 0
var secondsPassed = 0
#IBAction func startButtonPressed(_ sender: UIButton) {
let startB = sender.titleLabel?.text
totalTime = start
progressBar1.progress = 0.0
secondsPassed = 0
titleLabel.text = "coffee timer"
btnPressed1.titleLabel?.textColor = UIColor.white
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true)
}
#objc func updateTimer() {
if secondsPassed < totalTime {
secondsPassed += 1
progressBar1.progress = Float(secondsPassed) / Float(totalTime)
print(Float(secondsPassed) / Float(totalTime))
} else {
timer.invalidate()
titleLabel.text = "check coffee"
btnPressed1.titleLabel?.textColor = UIColor.green
let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
}
There's lots of different ways to handle this. Here is an outline of a possible approach:
Have an instance variable currentProgress, of type Int? If it's nil, none of your progress indicators is running.
Have an instance var stepCompletedInterval: Double
Create a struct to hold the different views you use to manage a progress step:
struct ProgressInfo {
let aButton: UIButton
let aLabel: UILabel
let aProgressIndicator: UIProgressIndicator
let secondsForThisStep: Int
}
Create an array of ProgressInfo, (let's call it progressInfoArray) and populate it with the buttons, labels, and progress indicators you have above. Also give each entry a value for secondsForThisStep.
When the user starts the process, set currentProgress to 0 (The first progress indicator.)
Now, for each step, set a stepCompletedInterval to the current time plus progressInfoArray[currentProgress].secondsForThisStep (The time at which the current step should complete.
Also start a 1-second repeating timer. Each time the timer fires, check to see if the current time is greater than stepCompletedInterval. If it is, increment currentProgress if there are still more steps to complete, and repeat the "now for each step" part above.
That is a rough outline of how you might go about it. I'm not completely clear on what your start buttons and btnPressed1 to btnPressed4 are supposed to do, so I'll leave that for you.
You'll need to adapt the approach I've outlined to your needs. It isn't code, it's an approach. I'm not going to give you code.

How to retrieve filled TextField from persistence

I have an error when loading secondViewController with a textField and an action button so the user can fill it with some number and get it saved to UserDefaults
The idea is to be able to come back to secondVC and that the TextField shows there with the same value that input originally by the User
class MainViewController: UIViewController {
#IBOutlet weak var A3TextField: UITextField!
#IBAction func calc(_ sender: Any) {
let A3 = Cell(name: "A3", sheet: "", value: Double(A3TextField.text!)!)
print(A3)
Cell.saveCellsUserDefaults(cells: [A3], forKey: "main")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
class SecondViewController: UIViewController {
#IBOutlet weak var B3TextField: UITextField!
#IBAction func calc2(_ sender: Any) {
let B3 = Cell(name: "B3", sheet: "", value: Double(B3TextField.text!)!)
print(B3)
// persist
Cell.saveCellsUserDefaults(cells: [B3], forKey: "second")
}
override func viewDidLoad() {
super.viewDidLoad()
// retrieve from persists and draw in TextField
let cellB3FromUD = Cell.getCellsUserDefaults(forKey: "second")
print("---> cellB3FromUD \(cellB3FromUD[0].value)")
B3TextField.text = "\(cellB3FromUD[0].value)"
}
}
struct Cell: Codable {
var name: String = ""
var sheet: String = ""
var value: Double = 0
init(name: String, sheet: String, value: Double) {
self.name = name
self.sheet = sheet
self.value = value
}
static func saveCellsUserDefaults(cells: [Cell], forKey: String) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(cells) {
let defaults = UserDefaults.standard
defaults.set(encoded, forKey: forKey)
}
}
static func getCellsUserDefaults(forKey: String)-> [Cell] {
var cells = [Cell]()
let decoder = JSONDecoder()
if let cellData = UserDefaults.standard.data(forKey: forKey) {
if let cellX = try? decoder.decode([Cell].self, from: cellData) {
cells = cellX
return cellX
}
}
return cells
}
}

Retain countdown timer value when switching between view controllers

I'm working on a trip countdown app that also has weather forecast built in.
Things are working pretty well, but when I switch from countdown timer to weather forecast, then come back, the countdown timer is reset.
Here's my countdown view controller code:
import UIKit
class CountdownVC: UIViewController {
var timer = Timer()
let userCalendar = Calendar.current
let requestedComponent: Set<Calendar.Component> = [.day,.hour,.minute,.second]
var departureDateTime: Date?
#IBOutlet weak var imageView: UIImageView!
let images = [
UIImage(named: "MK.png")!,
UIImage(named: "SSE1.png")!,
UIImage(named: "TofT.png"),
UIImage(named: "TofL1.png")!]
var index = 0
let animationDuration: TimeInterval = 0.25
let switchingInterval: TimeInterval = 15
func animateImageView()
{
CATransaction.begin()
CATransaction.setAnimationDuration(animationDuration)
CATransaction.setCompletionBlock {
DispatchQueue.main.asyncAfter(deadline: .now() + self.switchingInterval) {
self.animateImageView()
}
}
let transition = CATransition()
transition.type = kCATransitionFade
imageView.layer.add(transition, forKey: kCATransition)
imageView.image = images[index]
imageView.contentMode = .scaleAspectFill
imageView.alpha = 0.5
CATransaction.commit()
index = index < images.count - 1 ? index + 1 : 0
}
#IBOutlet weak var departureDateTimePicker: UIDatePicker!
#IBAction func departureDateTimePicker(_ sender: Any) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy H:mm:ss"
departureDateTimePicker.addTarget(self, action: #selector(handler), for: UIControlEvents.valueChanged)
}
#IBOutlet weak var selectDepartureDateTimeLabel: UILabel!
#IBOutlet weak var daysLabel: UILabel!
#IBOutlet weak var hoursLabel: UILabel!
#IBOutlet weak var minutesLabel: UILabel!
#IBOutlet weak var secondsLabel: UILabel!
func handler(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy H:mm:ss"
let departureDateTimeString = dateFormatter.string(from: departureDateTimePicker.date)
departureDateTime = dateFormatter.date(from: departureDateTimeString)
}
func printTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy H:mm:ss"
let startTime = Date()
let endTime = departureDateTime
let timeDifference = userCalendar.dateComponents(requestedComponent, from: startTime, to: endTime!)
let startTimeDouble: Double = startTime.timeIntervalSinceReferenceDate
var endTimeDouble: Double?
endTimeDouble = (endTime?.timeIntervalSinceReferenceDate)
if endTimeDouble! > startTimeDouble {
daysLabel.text = "\(timeDifference.day!) Days"
hoursLabel.text = "\(timeDifference.hour!) Hours"
minutesLabel.text = "\(timeDifference.minute!) Minutes"
secondsLabel.text = "\(timeDifference.second!) Seconds"
} else {
timer.invalidate()
daysLabel.text = ""
hoursLabel.text = ""
minutesLabel.text = ""
secondsLabel.text = ""
}
}
func runTimer() {
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(printTime), userInfo: nil, repeats: true)
timer.fire()
}
#IBOutlet weak var startBtn: UIButton!
#IBAction func startBtnPressed(_ sender: Any) {
handler(sender: departureDateTimePicker)
printTime()
runTimer()
selectDepartureDateTimeLabel.text = "Time to departure"
departureDateTimePicker.isHidden = true
startBtn.isHidden = true
}
#IBOutlet weak var resetBtn: UIButton!
#IBAction func resetBtnPressed(_ sender: Any) {
timer.invalidate()
selectDepartureDateTimeLabel.text = "Select departure date & time"
departureDateTimePicker.isHidden = false
startBtn.isHidden = false
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy H:mm:ss"
let startTime = Date()
let endTime = startTime
let timeDifference = userCalendar.dateComponents(requestedComponent, from: startTime, to: endTime)
daysLabel.text = "\(timeDifference.day!) Days"
hoursLabel.text = "\(timeDifference.hour!) Hours"
minutesLabel.text = "\(timeDifference.minute!) Minutes"
secondsLabel.text = "\(timeDifference.second!) Seconds"
}
#IBAction func goToWeatherBtnPressed(_ sender: Any) {
performSegue(withIdentifier: "goToWeatherVC", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
imageView.image = images[index+1]
animateImageView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Fatal error when unwrapping a segued string (swift3)

This is my code I don't know what I did wrong. All of the problems are in function steve. LebelText is a timer timer label that is segued from another view controller. So i want to take lebetText convert it to a int to subtract 1 from it then reconvert it back to a string to display the number.
This is view Controller a. The texted being segued is lebelText.
import UIKit
class testViewController: UIViewController {
#IBOutlet var lazel: UILabel!
#IBOutlet var plax: UIButton!
#IBOutlet var stopx: UIButton!
var timer = Timer()
var counter = 0.0
var isRunning = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController : restultViewController = segue.destination as! restultViewController
DestViewController.LebelText = lazel.text!
}
#IBAction func play(_ sender: Any) {
if !isRunning{
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(testViewController.update), userInfo: nil, repeats: true)
}
plax.isEnabled = false
stopx.isEnabled = true
}
#IBAction func stop(_ sender: Any) {
plax.isEnabled = true
stopx.isEnabled = false
timer.invalidate()
isRunning = false
}
func update(){
counter += 0.1
lazel.text = String(format: "1%f", counter)
lazel.text = "\(counter)"
}}
this is view controller b. The goal is to go to take lebelText convert it to a int to subtracted 1 from it. Then convert it back to a string so it can be displayed.
import UIKit
class restultViewController: UIViewController {
#IBOutlet var dxe: UILabel!
var LebelText = String()
let myInt = Int()
override func viewDidLoad() {
super.viewDidLoad()
steve()
}
func steve(){
var eq = LebelText
var intValue = Int(eq)
let vx = intValue! - 1
let ramit = String(vx)
dxe.text = ramit
}
ok so to get rid of the optional and to be sure it all works you should do like
if let intValue = Int(eq) {
vx = intValue - 1
dxe.text = String(vx)
} else {
//do some stuff if you cannot convert eq to Int
}
but I would recommend you to start with some easier tasks, it looks like you did not completely learn basics.
import UIKit
class restultViewController: UIViewController {
#IBOutlet var someLabel: UILabel!
public var myText: String?
override func viewDidLoad() {
super.viewDidLoad()
self.parseData()
}
private func parseData(){
guard let unwrapedText = self.myText else {
//you didn't pass string
return
}
if let myInt = Int(unwrapedText) {
myInt = myInt - 1
self.someLabel.text = String(myInt)
} else {
//you string is not convertable to int
}
}
}
You Can just do this.
import UIKit
class restultViewController: UIViewController {
#IBOutlet var dxe: UILabel!
var LebelText = String()
let myInt = Int()
override func viewDidLoad() {
super.viewDidLoad()
steve()
}
func steve(){
var eq = Int(LebelText.text)
eq = eq - 1
dxe.text = String(eq)
}

Remove the UIView at Runtime and Automatically Correct the UI

I have a UIViewController. I have made a MyProfile section. Now what i want to do is that if a person has only one picture then the 4 images section (which is a uiview) disappear and my UI (AboutLabel and TextSection comes up) will set according to that
Please see this picture: https://www.dropbox.com/s/gwokb8ge4pu5cw3/MyProfile.png?dl=0
class MyProfileViewController: UIViewController , UIImagePickerControllerDelegate{
#IBOutlet weak var sidebarButton: UIBarButtonItem!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var ageLabel: UILabel!
#IBOutlet weak var totalPicView: UIView!
#IBOutlet weak var aboutMeLabel: UITextView!
var imagesArray = [UIImageView]()
var tag: Int?
var check = false
var myUserInfo: UsersInformation!
var age: Int?
override func viewDidLoad() {
super.viewDidLoad()
if revealViewController() != nil
{
// revealViewController().rearViewRevealWidth = 62
sidebarButton.target = revealViewController()
sidebarButton.action = #selector(SWRevealViewController.revealToggle(_:))
//revealViewController().rightViewRevealWidth = 150
//rightReveal.target = revealViewController()
//rightReveal.action = "rightRevealToggle:"
view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
if NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) != nil
{
let uid = DataService.ds.currentUserID
DataService.ds.currentUserRef.observeEventType(.Value, withBlock: { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]
{
if let userDictionary = snapshot.value as? Dictionary<String , AnyObject>
{
print("ProfileData")
self.myUserInfo = UsersInformation(id:uid, userInfo: userDictionary)
}
}
/*SavingDataFUnction*/
self.setProfileData()
})
}
}
func setProfileData()
{
age = giveMeAge()
let width = view.frame.width
let height = view.frame.height
print("w:\(width) ; h \(height)")
/*Basic Information*/
self.nameLabel.text = myUserInfo.uName
self.ageLabel.text = "Age: " + String(age!)
self.aboutMeLabel.text = myUserInfo.about
if myUserInfo.imageUrl[0] == noImageUrl
{
profilePic.image = UIImage(named: "Profile")
/*Hide totalPicView and Adjust aboutLabel and TextView*/
//totalPicView.viewWithTag(101)?.hidden = true
//totalPicView.frame.size.height = 0
}
else if myUserInfo.imageUrl.count >= 1
{
/*FirstPic is Profile Pic*/
let profile = myUserInfo.imageUrl[0]
profilePic.kf_setImageWithURL(NSURL(string: profile))
for i in 0 ... 3
{
let url = self.myUserInfo.imageUrl[i]
let imgOne = UIImageView(frame: CGRectMake(89.5 * CGFloat(i), 0, 89.5, totalPicView.frame.height))
imgOne.kf_setImageWithURL(NSURL(string: url))
imgOne.tag = 11 + i
imagesArray.append(imgOne)
self.totalPicView.addSubview(imgOne)
}
for image: UIImageView in imagesArray
{
image.userInteractionEnabled = true
image.clipsToBounds = true
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.setImage))
image.addGestureRecognizer(tapGesture)
}
}
}
func setImage(gesture: UITapGestureRecognizer) {
print(gesture.view?.tag)
tag = gesture.view?.tag
performSegueWithIdentifier("showImages", sender: self)
//presentViewController(imagePicker, animated: true, completion: nil)
}
func setMyUI(imageView: UIImageView)
{
aboutMeLabel.layer.borderColor = UIColor.blackColor().CGColor
aboutMeLabel.layer.cornerRadius = 5
aboutMeLabel.layer.borderWidth = 1
}
func giveMeAge() -> Int
{
let dob = myUserInfo.dob
let todaysDate = NSDate() //dateFromString("2015-02-04 23:29:28", format: "yyyy-MM-dd HH:mm:ss")
let dateFormater = NSDateFormatter()
dateFormater.dateFormat = "MM/dd/yyyy"
let currentDate = dateFormater.dateFromString(dateFormater.stringFromDate(todaysDate))
let myDob = dateFormater.dateFromString(dob)
let calendar: NSCalendar = NSCalendar.currentCalendar()
let age = calendar.components(.Year, fromDate: myDob! , toDate: currentDate!, options: [])
return age.year
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImages"
{
let dest = segue.destinationViewController as! ProfileImages
dest.arrarayOfImages = imagesArray
dest.tag = tag
dest.uname = myUserInfo.uName
dest.myage = age
}
}
}
Ok if I understand correctly you want to remove the UIView section with the 4 UIImageViews if the user has just one/no picture/s. Why not try with an if statement in your viewDidLoad (Swift 3 syntax):
if(yourImageViewArray.count <= 1){
yourUIViewForImages.isHidden = true
}
Once your UIView yourUIViewForImages is hidden, your stack should adjust accordingly. Unless you have hardcoded CGRect values (x,y) for your About sections. It would really help to post your code as already mentioned in your comments section.

Resources