4

So I am trying to create a view that displays a large text view that's editable. In the storyboard it's edited to display the text "Take your notes here (Swipe Down to dismiss the keyboard): " as a placeholder.

I'd like for it to remember when a user edits the text other than from that... so I made an if statement using != That comparator works for comparing strings in swift. I'm not sure that it will get approved by the app store review because they recommend isEqualToString().

Anyways the code below is for that view... It's not remembering the text entered if it's altered by the user from the placeholder. It recognizes that it was altered but when you go back to the view it displays the default placeholder again... Help?

import Foundation
import UIKit

class MessageNotesViewController: UIViewController, UITextViewDelegate {

@IBOutlet weak var messageNotes: UITextView!
@IBOutlet var swiped: UISwipeGestureRecognizer!

var placeholder = "Take your notes here (Swipe Down to dismiss the keyboard): "

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)

    messageNotes.delegate = self
    messageNotes.text = placeholder

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

@IBAction func openIn(_ sender: AnyObject) {

    print("Share with Social Media or Copy to Notes")
    //let textToShare = messageNotes.attributedText

       // let objectsToShare = [textToShare]
        //let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)


    //activityVC.popoverPresentationController?.sourceView = (sender as! UIView)
    //self.present(activityVC, animated: true, completion: nil)


    if let notes = messageNotes.text {
        let avc = UIActivityViewController.init(activityItems: [notes], applicationActivities: nil)

        avc.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
        self.present(avc, animated: true) {
            print("completed")
        }
    }
}

func touchesBegan(_ messageNotes: UITextField) -> Bool {
    self.view.endEditing(true)
    return false
}


//let defaults = NSUserDefaults.

override func viewWillDisappear(_ animated: Bool) {
    //PrepareForSegue didn't quite work
    print("View Will Disappear")

    //Testing if the user has entered any text if so preserve entered text
    if messageNotes.text != placeholder {

        //viewDidLoad(typedText)
        print("the user altered the text in some way. \n")

        placeholder = messageNotes.text
        // assigns new placeholder
    }
    else{
        // do something else - if needed
    }
}
}

//Sub class decleration for ActivityForNotesViewController as called in openIn
class ActivityForNotesViewController: UIActivityViewController {

internal func _shouldExcludeActivityType(_ activity: UIActivity) -> Bool {
    let activityTypesToExclude = [
    ]

    if let actType = activity.activityType() {
        if activityTypesToExclude.contains(actType) {
            return true
        }
        else if super.excludedActivityTypes != nil {
            return super.excludedActivityTypes!.contains(actType)
        }
    }
    return false
}
}

There were some compiling errors when trying to implement the answer below.

In the viewWillAppear function the compiler says "Cannot call value of non-function type 'UserDefaults'" - the compiler highlights the line if let newText line with the UserDefaults.standardUserDefaults() underlined in red.

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)

    messageNotes.delegate = self
    messageNotes.text = placeholder

    if let newText = UserDefaults.standardUserDefaults().objectForKey("textKey"){
        if newText.length > 0 {
            messageNotes.text = newText
        }
    }

}

The Same compiling error is found in the viewWillDisappear function:

override func viewWillDisappear(_ animated: Bool) {
    //Prepare for segue didn't quite work for what I need
    print("View Will Disappear")

    //Testing if the user has entered any text if so preserve entered text
    if messageNotes.text != placeholder {

        //viewDidLoad(typedText)
        print("the user altered the text in some way. \n")

        UserDefaults.standardUserDefaults().setObject(messageNotes.text!, forKey:"textKey")

        // assigns new placeholder
    }
    else{
        // do something else - if needed
    }
}
}
KSigWyatt
  • 1,368
  • 1
  • 16
  • 33
  • My answer below should work for you. Also, you don't need to worry about using `!=` over `isEqualToString()` as long as it works. When reviewing, Apple cannot actually see your specific code. – Wyetro Jul 22 '16 at 14:45
  • @WMios Edited to reflect function / compiler errors – KSigWyatt Jul 22 '16 at 15:17
  • check out my modified code. I was using Swift 2 syntax unknowingly - checked the doc I had linked to – Wyetro Jul 22 '16 at 15:18
  • @WMios I think I may have Fixed the error... I used `UserDefaults.standard.object(forKey: "textKey")` instead of `UserDefaults.standardUserDefaults().object("textKey")`... Also it says that in the if statement the line `messageNotes.text = newText` needs to be replaced so I did `messageNotes.text = newText as! String`... and all the compiler errors went away. – KSigWyatt Jul 22 '16 at 15:28
  • Yeah, that's pretty much the same thing as the change I had made 14 minutes ago. I didn't add the cast to string. – Wyetro Jul 22 '16 at 15:30
  • Did this end up solving your issue? If so feel free to accept my answer! – Wyetro Jul 22 '16 at 15:39

1 Answers1

0

You need to save the changes somewhere, I'd recommend UserDefaults, which is a good way to save user preferences, and other small pieces of data.

I'd replace this in viewWillDisappear:

placeholder = messageNotes.text

with

UserDefaults.standardUserDefaults().set(messageNotes.text!, forKey:"textKey")

And in viewWillAppear I'd add:

messageNotes.text = placeholder
if let newText = UserDefaults.standardUserDefaults().object("textKey"){
    if newText.length > 0 {
        messageNotes.text = newText as! String
    }
}
Graham
  • 7,431
  • 18
  • 59
  • 84
Wyetro
  • 8,439
  • 9
  • 46
  • 64
  • Is there any imports or anything I need to make because it's giving a compiler error of : Cannot call value of non-function type 'UserDefaults' ? I'll try looking at the documentation page you posted to look at it. – KSigWyatt Jul 22 '16 at 14:52
  • On which line? And are you sure you're using Swift 3? If not you can add `NS` to before `UserDefaults` to make it `NSUserDefaults`. – Wyetro Jul 22 '16 at 14:53
  • Also note, that `ObjectForKey` should be `objectForKey`. – Wyetro Jul 22 '16 at 14:55
  • 1
    When I added the code you suggested it gave me that error. Maybe I'm doing something wrong though. It's specifically complaining about both instances of UserDefaults.standardUserDefaults() – KSigWyatt Jul 22 '16 at 14:57
  • Did you not just copy and paste it? And what happens if you add the NS prefix? – Wyetro Jul 22 '16 at 14:58
  • I did copy and paste it. I thought I might have to change some variable names or something like you'd normally do when you copy and paste stuff but it works... it just complains and gives an error so the Build fails When I add NS to UserDefaults it says that "NSUserDefaults has been replaced with UserDefaults" ... Could just be something new to Swift 3.0 – KSigWyatt Jul 22 '16 at 15:02
  • 1
    UserDefaults should work in Swift 3... weird that it recognizes to switch NSUserDefaults to UserDefaults but then won't build. Does sound like a bug. – Wyetro Jul 22 '16 at 15:03
  • Wait can you edit your post with the entire function that gives the error (just add it to the end), I think I know what the issue is – Wyetro Jul 22 '16 at 15:05
  • @KSigWyatt, I realized what I think might be the issue. In Swift 3, setObject became set and ObjectForKey became object. I adjusted my answer. – Wyetro Jul 22 '16 at 15:16