1

The error that is crashing my app when I click the save button

-[BlogApp.Blog encodeWithCoder:]: unrecognized selector sent to instance 0x7fbe31d33800

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ''-[BlogApp.Blog encodeWithCoder:]: unrecognized selector sent to instance 0x7fbe31d33800'

Code in MainController.swift to declare 'path'

let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]

Code in button that is supposed to save arrays

// After Updating Table, Save Arrays
var success = false

success = NSKeyedArchiver.archiveRootObject(gameArray, toFile: path)

if success {
  print("Saved Blogs")
} else  {
  print("Didn't Save Blogs")
}

Code that handles NSCoding and my Blog Objects

import UIKit

class BlogsCoding: NSObject, NSCoding {

var blogList : [Blog]

init(blogList : [Blog]) {
    self.blogList = blogList
}

convenience required init?(coder aDecoder: NSCoder) {

    guard let blogList = aDecoder.decodeObject(forKey: "blogs") as? [Blog]
        else {
            return nil
    }
    self.init (blogList : blogList)
}

func encode(with aCoder: NSCoder) {

    aCoder.encode(blogList, forKey: "blogs")
 }
}

class Blog: NSObject, NSCoding { // To conform to NSCoding

// Strings
var blogName: String?
var blogStatus1: String?
var blogStatus2: String?
var blogURL: String?
var blogID: String?
var blogType: String?
var blogDate: String?
var blogPop: String?
var blogList : [Blog] // To conform to NSCoding

override init() {

}
// Converting Strings into Objects
init(blogName bName: String,
     andBlogStatus1 bStatus1: String,
     andBlogStatus2 bStatus2: String,
     andBlogURL bURL: String,
     andBlogID bID: String,
     andBlogType bType: String,
     andBlogDate bDate: String,
     andBlogPop bPop: String,
     blogList : [Blog]) // To conform to NSCoding
{
    super.init()

    self.blogName = bName
    self.blogStatus1 = bStatus1
    self.blogStatus2 = bStatus2
    self.blogURL = bURL
    self.blogID = bID
    self.blogType = bType
    self.blogDate = bDate
    self.blogPop = bPop
    self.blogList = blogList // To conform to NSCoding
 }

 // To conform to NSCoding
 convenience required init?(coder aDecoder: NSCoder) {

    guard let blogList = aDecoder.decodeObject(forKey: "blogs") as? [Blog]
        else {
            return nil
    }
    self.init (coder : blogList) // *New error is here*
}

func encode(with aCoder: NSCoder) {

    aCoder.encode(blogList, forKey: "blogs")
}

}

In MainController.swift

// Retrieving Data from Server
func retrieveData() {

    let getDataURL = "http://blogtest.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {

        let data: Data = try Data(contentsOf: url as URL)
        jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Looping through jsonArray
        for i in 0..<jsonArray.count {

            // Create Blog Object
            let bID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String
            let bName: String = (jsonArray[i] as AnyObject).object(forKey: "blogName") as! String
            let bStatus1: String = (jsonArray[i] as AnyObject).object(forKey: "blogStatus1") as! String
            let bStatus2: String = (jsonArray[i] as AnyObject).object(forKey: "blogStatus2") as! String
            let bURL: String = (jsonArray[i] as AnyObject).object(forKey: "blogURL") as! String
            // New
            let bType: String = (jsonArray[i] as AnyObject).object(forKey: "blogType") as! String
            let bDate: String = (jsonArray[i] as AnyObject).object(forKey: "blogDate") as! String
            let bPop: String = (jsonArray[i] as AnyObject).object(forKey: "blogPop") as! String
            // NSCoding
            let bList: NSObject = ((jsonArray[i]) as! NSObject).value(forKey: "blogList") as! NSObject

            // Add Blog Objects to Blog Array
            blogArray.append(Blog(gameName: bName, andBlogStatus1: bStatus1, andBlogStatus2: bStatus2, andBlogURL: bURL, andBlogID: bID, andBlogType: bType, andBlogDate: bDate, andBlogPop: bPop, blogList: bList as! [Game]))

        }
    }
    catch {
        print("Error: (Retrieving Data)")
    }

    myTableView.reloadData()
}

I'm obviously doing something wrong as its crashing but I was following a tutorial and I can't seem to figure out what I'm doing wrong, my guess is how I'm saving it? Or 'path' is going wrong? It's supposed to save into a plist correct? Thank you!

  • Error when conforming Blog : NSObject to NSCoding

Cannot convert value of type '[Blog]' to expected argument type 'NSCoder'

WokerHead
  • 947
  • 2
  • 15
  • 46
  • 3
    Your `Blog` class has to conform to `NSCoding` – dan Jun 09 '17 at 20:36
  • okay so I added ", NSCoding" and now I add the same code as in BlogsCoding? – WokerHead Jun 09 '17 at 20:38
  • 1
    Yes. You are saving a `BlogsCoding` which is `NSCoding` compliant (has encode/decode), so you can call `NSKeyedArchiver.archiveRootObject()` on it. But, since `BlogsCodings` has at some points `Blogs` object, and that you'll save them (you encode/decode them: `aDecoder.decodeObject(forKey: "blogs") as? [Blog]`), they need to be `NSCoding` compliant too. It will be called at "each level and sublevel". – Larme Jun 09 '17 at 22:10
  • @Larme I conformed NSCoding and I get an error at this line self.init (coder : blogList) saying Cannot convert value of type '[Blog]' to expected argument type 'NSCoder'. I edited the code above to show the error and new code so you can see. – WokerHead Jun 09 '17 at 23:12

0 Answers0