self is immutable - macos

I have a class, Task, with a 'count' property. The end goal is to increase the count by 1.
In a playground, this is working:
class Task: NSObject {
var name: String
var count: Int
init(name:String, count:Int) {
self.name = name
self.count = count
}
}
var test = Task(name: "test", count: 0)
test.count += 1
// => 1
But in my actual project, it's getting this error:
Left side of mutating operator isn't mutable: 'self' is immutable
In my ViewController, I have an #IBAction function that I'd like to trigger the count increase, so that's where the error is occurring. Here's a trimmed down version:
#IBAction func addTask(sender: AnyObject) {
currentTask = newTaskInput.stringValue
let x = Task(name: currentTask, count: 0)
currentTaskObj = x
// error occurs here
currentTaskObj!.count += 1
}
Any idea how to fix this? I must be missing something because it's working in a playground exactly how I'd like. Huge thanks in advance!
Edit: here's the actual class from my project (I changed sessions to count for the examples above):
class Task: NSObject, NSCoding {
var name: String
var sessions: Int
var time: String = ""
init(name:String, sessions:Int, time:String? = "") {
self.name = name
self.sessions = sessions
self.time = time!
}
required convenience init(coder aDecoder: NSCoder) {
var name = aDecoder.decodeObjectForKey("name") as! String
var sessions = aDecoder.decodeObjectForKey("sessions") as! Int
var time = aDecoder.decodeObjectForKey("time") as! String
self.init(name: name, sessions: sessions, time: time)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.name, forKey: "name")
aCoder.encodeObject(self.sessions, forKey: "sessions")
aCoder.encodeObject(self.time, forKey: "time")
}
}

Related

How to make NSSpellChecker work with NSDocument?

I have a core data / document-driven macOS app, using Swift and I struggle on combining the out-of-the-box spell checking API with an NSDocument (NSPersistentDocument in my case)
It took me more time than it should take, but this is what I got, mostly guided by this great answer:
class VTDocument: NSPersistentDocument, NSChangeSpelling {
[...]
private let spellchecker = SpellChecker()
#IBAction func showGuessPanel(_ sender: Any?){
spellchecker.startSpellCheck(nodes: Array(db.nodes), tag: 0)
}
#IBAction #objc func changeSpelling(_ sender: Any?){
spellchecker.replace(with: "Test")
}
This is leading me to see the NSSpellChecker.spellingPanel, correctly showing the word to correct. However, the changeSpelling function should be "called" by the panel but is never called. The above spellChecker is a simple wrapper around the NSSpellChecker that keeps the status between function calls.
The SpellChecker class looks like this.
import Cocoa
class SpellChecker {
let checker = NSSpellChecker.shared
let count: UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.allocate(capacity: 1)
var nodes = Array<Node> ()
var nodeNr = 0
var stringPos = 0
var range: NSRange = NSRange()
func startSpellCheck(nodes: [Node], tag: Int ) {
self.nodes = nodes
nodeNr = 0
stringPos = 0
continueChecking()
}
func continueChecking(){
if nodes.count == 0 {
return
}
if nodeNr >= nodes.count {
checker.updateSpellingPanel(withMisspelledWord: "")
checker.spellingPanel.orderFront(self)
return
}
if let nodeText = nodes[nodeNr].label {
range = checker.checkSpelling(of: nodeText, startingAt: stringPos, language: nil, wrap: false, inSpellDocumentWithTag: 0, wordCount: count)
if count.pointee > 0 {
stringPos = range.lowerBound
checker.updateSpellingPanel(withMisspelledWord: nodeText[range])
checker.spellingPanel.orderFront(self)
return
}
}
nodeNr = nodeNr + 1
continueChecking()
}
func replace(with: String){
if let nodeText = nodes[nodeNr].label {
let text = nodeText as NSString
text.replacingCharacters(in: range, with: with)
nodes[nodeNr].label = text as String
}
}
}

NSCoder crash on decodeBool forKey (Xcode 8, Swift 3)

I have this simple class
import UIKit
class SimpleModel: NSObject, NSCoding {
var name : String!
var done : Bool!
init(name:String) {
self.name = name
self.done = false
}
internal required init?(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.done = aDecoder.decodeBool(forKey: "done") // BUG HERE
}
func encode(with encoder: NSCoder) {
encoder.encode(self.name, forKey: "name")
encoder.encode(self.done, forKey: "done")
}
}
the save code:
let data = NSKeyedArchiver.archivedData(withRootObject: storageArray)
UserDefaults.standard.set(data, forKey: "storage")
UserDefaults.standard.synchronize()
the read code:
if let data = UserDefaults.standard.data(forKey: "storage") {
storageArray = NSKeyedUnarchiver.unarchiveObject(with: data) as! [SimpleModel]
}
the problem occurs when the NSKeyedUnarchiver does it's job. I can not understand where the problem comes from.
Thanks!
the trick is remove ! form the primitive types.
If you put ! you are saying "make an implicit-unwrapped optional" so the encoder will archive as NSNumber instead of Bool (or Int, Double).
If you remove ! the encoder will archive as Bool and things works as expected (I spent an "incident" and this solution is provided by Apple)
Bool and Int have new methods:
self.x = Int(decoder.decodeCInt(forKey: "Speed"))
self.y = decoder.decodeObject(forKey: "Serial") as! String
self.z = Bool(decoder.decodeBool(forKey: "Direction") )
I had the same Problem.
Try this:
self.done = aDecoder.decodeObject(forKey: "done") as? Bool ?? aDecoder.decodeBool(forKey: "done")

Swift does not conform to protocol 'OS_dispatch_queue'

I'm trying to implement an asynchronous function as told in this topic but I always get the following error from Xcode : Type 'dispatch_queue_t!' does not conform to protocol 'OS_dispatch_queue'
Here's my code:
#IBAction func buyButton(sender: AnyObject) {
// get wanted symbol
let symbol = symbolField.text!
// get price of share
var priceShare :Double = 0
_ = lookup(symbol) { name, symbol, price in
dispatch_async(dispatch_get_main_queue()) {
priceShare = price
}
}
buy(symbol, number: 1, price: priceShare)
}
Here's the lookup function:
func lookup(entry : NSString, completion: ((name :String, symbol :String, price :String) -> Void)) {
// define return values
var name = String()
var symbol = String()
var price = String()
// define URL
let url = NSURL(string: "http://yahoojson.gobu.fr/symbol.php?symbol=\(entry)")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if let urlContent = data {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers)
name = jsonResult["name"] as! String
symbol = jsonResult["symbol"] as! String
price = jsonResult["price"]!!.stringValue as String
completion(name: name, symbol: symbol, price: price)
} catch {
print(error)
}
}
}
// run the task
task.resume()
}
Any hint on what I could be doing wrong?
I figure it out by myself. There was a bug inside on my code.
On the line
priceShare = price
I needed to put
priceShare = Double(price)!
since priceShare require a Double. Don't understand why Xcode didn't tell me so.

PFQuery not getting Object ID

The code below checks Parse to see if an email address has been verified. I am able to retrieve the object ID from Core Data (I saved it in a previous view controller) but when it comes to query.getObjectInBackgroundWithId(userID), userID is for some reason nil. I get the error:
Error: no results matched the query (Code: 101, Version: 1.6.0)
import UIKit
import CoreData
class HomePage: UIViewController{
#IBOutlet var emailMessage: UILabel!
//var userID: String!
override func viewDidLoad() {
super.viewDidLoad()
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
var results: NSArray = context.executeFetchRequest(request, error: nil)!
var res = results [0] as NSManagedObject
var userID = res.valueForKey("userID") as String
println (userID) //Correct ID is retrieved here
var query = PFQuery(className:"User")
query.getObjectInBackgroundWithId(userID) { //ID becomes nil
(email: PFObject!, error: NSError!) -> Void in
if error == nil {
let checkEmail = email["emailVerified"] as Bool
if (checkEmail != true)
{
self.emailMessage.hidden = false
}
else
{
self.emailMessage.hidden = true
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I think the problem lies in the way you're getting a PFQuery for the user. You should use the special user query:
var query = PFUser.query()
See Users - Querying, in the Parse docs.
The User table (as well as all other parse-managed classes) in parse is prefixed by underscore, so you should fix this line:
var query = PFQuery(className:"_User")

errors while trying to compare a string to element in array

let verbList: [String] = ["hacer", "ser", "estar"]
let POVList: [String] = ["él / usted","ella / usted","ellas / ustedes","ellos / ustedes","tú","yo","nosotros",]
let correctConjugation: [[String]] = [["hace","hace","hacen","hacen","haces","hago","hacemos"], ["es","es","son","son","eres","soy","somos"], ["está","está","estan","estan","estas","estoy","estamos"]]
func randomVerb() -> Int { //creates and returns a random number for the prefix arrray
var randomVerb = Int(arc4random_uniform(3))
return randomVerb
}
func randomPrefix() -> Int { //creates and returns a random number for the verb array
var randomPrefix = Int(arc4random_uniform(7))
return randomPrefix
}
#IBAction func changeVerb(sender: AnyObject) {
Verb.text = verbList[randomVerb()]
POV.text = POVList[randomPrefix()]
userResponse.backgroundColor = UIColor.whiteColor()
userResponse.text = ""
}
#IBAction func checkResponse(sender: AnyObject) {
var userResponseA: String
userResponseA = userResponse.text
if (userResponseA == correctConjugation[randomVerb()[randomPrefix()]]){
userResponse.backgroundColor = UIColor.greenColor()
} else {
userResponse.backgroundColor = UIColor.redColor()
}
}
So I get two errors here (in the if statement in checkResponse): first, "int does not have a member named 'subscript'" and if I just take out the call for the function in the if statement I get: "'String' is not convertible to 'Mirror Disposition'"
I really have no idea why this is not working. Bear with me, as I am an Xcode noob just trying to get a better grade in spanish.
Very close - just need to have your subscripts separated:
if (userResponseA == correctConjugation[randomVerb()][randomPrefix()]) {
// ...
}
When working with an array of arrays (in this case correctConjugation), each subscript takes you one level down.
For the other issue, you want a couple variables to hold the current verb and prefix indexes:
class VC: UIViewController {
// list declarations here
var verbIndex = 0
var povIndex = 0
#IBAction func changeVerb(sender: AnyObject) {
verbIndex = randomVerb()
povIndex = randomPrefix()
Verb.text = verbList[verbIndex]
POV.text = POVList[povIndex]
userResponse.backgroundColor = UIColor.whiteColor()
userResponse.text = ""
}
#IBAction func checkResponse(sender: AnyObject) {
var userResponseA = userResponse.text
if (userResponseA == correctConjugation[verbIndex][povIndex]){
userResponse.backgroundColor = UIColor.greenColor()
} else {
userResponse.backgroundColor = UIColor.redColor()
}
}
}

Resources