2017-06-22 6 views
0

Verwenden von Swift 3Swift: Kein Zugriff auf den JSON-Code. (gefunden Null beim Auspacken)

Fehler verursacht einen Absturz, wenn ich in MainController.swift Schaltfläche followButtonClick klicken. blogID ist in Null, aber wenn ich mainArray drucken alle Objekte sind da, so dass es etwas falsch in meinem Code ist, dass ich nicht beheben kann. blogID wird nicht richtig zugegriffen.

fatal error: unexpectedly found nil while unwrapping an Optional value

Statt NSCoder und UserDefaults mit der gesamten Palette von mainArray und followedArray zu sparen, spare ich die blogsID gefolgt und dann diejenigen, die Anzeige, die wir durch Greifen der Objekte gespeichert sind, die ihre IDs gespeichert hatten.

MainController.swift

var mainArray = [Blog]() 
var followedArray = [Blog]() 
var filteredArray = [Blog]() 
var followedIdentifiers = Set<String>() 

// viewDidLoad 
override func viewDidLoad() { 
    super.viewDidLoad() 

    retrieveDataFromServer() 
    loadUserDefaults() 
} 

// Title for Header 
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 

if !(searchController.isActive && searchController.searchBar.text != "") { 

    if section == 0 { 
     return "Followed Blogs" 
    } 
    else { 
     return "All Blogs" 
    } 
} 
return "Filtered Blogs" 
} 

// Number of Rows in Section 
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

if !(searchController.isActive && searchController.searchBar.text != "") { 

    if section == 0 { 

     return followedArray.count 
    } 
    else if (section == 1) { 

     return mainArray.count 
    } 
} 
return filteredArray.count 
} 

// CellForRowAt indexPath 
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

let CellIdentifier = "Cell" 
var cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! CustomCell 

if cell != cell { 
    cell = CustomCell(style: UITableViewCellStyle.default, reuseIdentifier: CellIdentifier) 
} 

// Configuring the cell 
var blogObject: Blog 

if !(searchController.isActive && searchController.searchBar.text != "") { 
    if indexPath.section == 0 { 
     blogObject = followedArray[indexPath.row] 
     cell.populateCell(blogObject, isFollowed: true, indexPath: indexPath, parentView: self) 
    } 
    else if indexPath.section == 1 { 
     blogObject = mainArray[indexPath.row] 
     cell.populateCell(blogObject, isFollowed: false, indexPath: indexPath, parentView: self) 
    } 
} 
else { 
    blogObject = filteredArray[indexPath.row] 
    cell.populateCell(blogObject, isFollowed: false, indexPath: indexPath, parentView: self) 
} 

return cell 
} 

// Follow Button 
@IBAction func followButtonClick(_ sender: UIButton!) { 

    // Adding row to tag 
    let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: self.myTableView) 
    if let indexPath = self.myTableView.indexPathForRow(at: buttonPosition) { 

     // Showing Status Labels 
     let cell = self.myTableView.cellForRow(at: indexPath) as! CustomCell 
     cell.firstStatusLabel.isHidden = false 
     cell.secondStatusLabel.isHidden = false 

     // Change Follow to Following 
     (sender as UIButton).setImage(UIImage(named: "follow.png")!, for: .normal) 
     cell.followButton.isHidden = true 
     cell.followedButton.isHidden = false 

     // Checking wether to import from mainArray or filteredArray to followedArray 
     if !(searchController.isActive && searchController.searchBar.text != "") { 

      self.myTableView.beginUpdates() 

      // -*- Error breaks here -*- 
      // Save identifier into followedIdentifier array 
    self.followedIdentifiers.insert(mainArray[indexPath.row].blogID) 

      // ----- Inserting Cell to followedArray ----- 
      followedArray.insert(mainArray[indexPath.row], at: 0) 
      myTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .fade) 

      // ----- Removing Cell from mainArray ----- 
      mainArray.remove(at: indexPath.row) 
      let rowToRemove = indexPath.row 
      self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 1)], with: .fade) 

      self.myTableView.endUpdates() 

      myTableView.reloadData() 

      // After Updating Table, Save the Archived to UserDefaults 
      saveUserDefaults() 
     } 
     else { 

      self.myTableView.beginUpdates() 

      // Remove identifier into followedIdentifier array 
self.followedIdentifiers.remove(followedArray[indexPath.row].blogID) 

      // ----- Inserting Cell to followedArray ----- 
      let blogObject: Blog = filteredArray[indexPath.row] 
      let indexOfObjectInArray = mainArray.index(of: blogObject) 

      followedArray.insert(blogObject, at: 0) 

      // ----- Removing Cell from filteredArray ----- 
      filteredArray.remove(at: indexPath.row) 
      mainArray.remove(at: indexOfObjectInArray!) 
      let rowToRemove = indexPath.row 
      self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 0)], with: .fade) 

      self.myTableView.endUpdates() 

      myTableView.reloadData() 

      // After Updating Table, Save the Archived to UserDefaults 
      saveUserDefaults() 
     } 
    } 
} 

// Unfollow Button 
@IBAction func followedButtonClick(_ sender: UIButton!) { 

    // Adding row to tag 
    let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: self.myTableView) 
    if let indexPath = self.myTableView.indexPathForRow(at: buttonPosition) { 

     // Hiding Status Labels 
     let cell = self.myTableView.cellForRow(at: indexPath) as! CustomCell 
     cell.firstStatusLabel.isHidden = true 
     cell.secondStatusLabel.isHidden = true 

     // Change Following to Follow 
     (sender as UIButton).setImage(UIImage(named: "followed.png")!, for: .normal) 
     cell.followButton.isHidden = false 
     cell.followedButton.isHidden = true 

     self.myTableView.beginUpdates() 

     // Remove identifier into followedIdentifier array 
     self.followedIdentifiers.remove(followedArray[indexPath.row].blogID) 

     // ----- Inserting Cell to mainArray ----- 
     mainArray.insert(followedArray[indexPath.row], at: 0) 
     myTableView.insertRows(at: [IndexPath(row: 0, section: 1)], with: .fade) 

     // ----- Removing Cell from followedArray ----- 
     followedArray.remove(at: indexPath.row) 
     let rowToRemove = indexPath.row 
     self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 0)], with: .fade) 

     self.myTableView.endUpdates() 

     myTableView.reloadData() 

     // After Updating Table, Save the Archived to UserDefaults 
     saveUserDefaults() 
    } 
} 

// Saving UserDefaults 
func saveUserDefaults() { 

    let key = "followedID" 
    UserDefaults.standard.setValue(self.followedIdentifiers, forKey: key) 
    UserDefaults.standard.synchronize() 
} 

// Load UserDefaults 
func loadUserDefaults() { 

    let key = "followedID" 
    UserDefaults.standard.setValue(Array(self.followedIdentifiers), forKey: key) 
    self.followedIdentifiers = Set(UserDefaults.standard.stringArray(forKey: key)!) 
} 

// Retrieving Data from Server 
func retrieveDataFromServer() { 

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

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

     // Clear the arrays 
     self.followedArray = [Blog]() 
     self.mainArray = [Blog()] 

     // Looping through jsonArray 
     for jsonObject in jsonArray { 

      if let blog = Blog.createBlog(from: jsonObject as AnyObject) { 

       // Check if identifiers match 
       if followedIdentifiers.contains(blog.blogID) { 
        self.followedArray.append(blog) 
       } else { 
        self.mainArray.append(blog) 
       } 
      } 
     } 
    } catch { 
     print("Error: (Retrieving Data)") 
    } 
    myTableView.reloadData() 
} 

Blog.swift - Griffe der Blogs

import UIKit 

class Blog: NSObject, NSCoding { 

var blogName: String! 
var blogStatus1: String! 
var blogStatus2: String! 
var blogURL: String! 
var blogID: String! 
var blogType: String! 
var blogDate: String! 
var blogPop: String! 

static func createBlog(from jsonObject: AnyObject) -> Blog? { 

    guard let bID: String = jsonObject.object(forKey: "id") as? String, 
     let bName: String = jsonObject.object(forKey: "blogName") as? String, 
     let bStatus1: String = jsonObject.object(forKey: "blogStatus1") as? String, 
     let bStatus2: String = jsonObject.object(forKey: "blogStatus2") as? String, 
     let bURL: String = jsonObject.object(forKey: "blogURL") as? String, 
     let bType: String = jsonObject.object(forKey: "blogType") as? String, 
     let bDate: String = jsonObject.object(forKey: "blogDate") as? String, 
     let bPop: String = jsonObject.object(forKey: "blogPop") as? String 

     else { 
      print("Error: (Creating Blog Object)") 
      return nil 
} 

let blog = Blog() 
    blog.blogName = bName 
    blog.blogStatus1 = bStatus1 
    blog.blogStatus2 = bStatus2 
    blog.blogURL = bURL 
    blog.blogID = bID 
    blog.blogType = bType 
    blog.blogDate = bDate 
    blog.blogPop = bPop 
    return blog 
} 

convenience required init?(coder aDecoder: NSCoder) { 
    self.init() 
    self.blogName = aDecoder.decodeObject(forKey: "blogName") as! String 
    self.blogStatus1 = aDecoder.decodeObject(forKey: "blogStatus1") as! String 
    self.blogStatus2 = aDecoder.decodeObject(forKey: "blogStatus2") as! String 
    self.blogURL = aDecoder.decodeObject(forKey: "blogURL") as! String 
    self.blogID = aDecoder.decodeObject(forKey: "blogID") as! String 
    self.blogType = aDecoder.decodeObject(forKey: "blogType") as! String 
    self.blogDate = aDecoder.decodeObject(forKey: "blogDate") as! String 
    self.blogPop = aDecoder.decodeObject(forKey: "blogPop") as! String 
} 

func encode(with aCoder: NSCoder) { 
    aCoder.encode(blogName, forKey: "blogName") 
    aCoder.encode(blogStatus1, forKey: "blogStatus1") 
    aCoder.encode(blogStatus2, forKey: "blogStatus2") 
    aCoder.encode(blogURL, forKey: "blogURL") 
    aCoder.encode(blogID, forKey: "blogID") 
    aCoder.encode(blogType, forKey: "blogType") 
    aCoder.encode(blogDate, forKey: "blogDate") 
    aCoder.encode(blogPop, forKey: "blogPop") 
} 
} 
+0

welche Linie es auf nicht abstürzen? Verwenden Sie die im verknüpften Duplikat beschriebenen Debugging-Methoden – Paulw11

+0

In MainController, folgenButtonClick, 'self.followedIdentifiers.insert (mainArray [indexPath.row] .blogID)' – BroSimple

+0

So verwenden Sie den Debugger und erarbeiten, welcher Wert ist nil - ist 'self.followedIdentifiers 'Nil? ist 'mainArray [indexPath.row] .blogID' nil? – Paulw11

Antwort

0

Ihre unmittelbare Problem-Objekte ist, dass Sie eine implizit ungeöffneten optional blogID haben, die einen Wert nicht zugewiesen wurde. Die zugrunde liegende Ursache wird durch die Verwendung von implizit ausgepackten Optionalen maskiert, da sie den Speicherort nicht offenlegt, an dem Sie eine Blog Instanz nicht ordnungsgemäß initialisieren können.

Anstatt eine statische Funktion zum Erstellen eines Blog aus einem JSON-Wörterbuch zu verwenden, sollten Sie einen nicht initialisierbaren Initialisierer verwenden. Dadurch können Sie ggf. nicht optionale Eigenschaften verwenden und Ihnen einen Compiler- oder Laufzeitfehler geben, wenn das Objekt nicht korrekt initialisiert wird.

import Foundation 

class Blog: NSObject, NSCoding { 

    var blogName: String 
    var blogStatus1: String 
    var blogStatus2: String 
    var blogURL: String  // Note this should probably be a URL rather than a String 
    var blogID: String 
    var blogType: String 
    var blogDate: String // Note this should probably be a Date rather than a String 
    var blogPop: String 


    private init (name: String,status1: String,status2: String,url: String,id: String,type: String,date: String,pop: String) { 
     blogName = name 
     blogStatus1 = status1 
     blogStatus2 = status2 
     blogURL = url 
     blogID = id 
     blogType = type 
     blogDate = date 
     blogPop = pop 
     super.init() 
    } 

    convenience init?(jsonObject: [String:Any]) { 

     guard let bID = jsonObject["id"] as? String, 
      let bName = jsonObject["blogName"] as? String, 
      let bStatus1 = jsonObject["blogStatus1"] as? String, 
      let bStatus2 = jsonObject["blogStatus2"] as? String, 
      let bURL = jsonObject["blogURL"] as? String, 
      let bType = jsonObject["blogType"] as? String, 
      let bDate = jsonObject["blogDate"] as? String, 
      let bPop = jsonObject["blogPop"] as? String 

      else { 
       print("Error: (Creating Blog Object)") 
       return nil 
     } 

     self.init(name: bName, status1: bStatus1, status2: bStatus2, url: bURL, id: bID, type: bType, date: bDate, pop: bPop) 

    } 

    convenience required init?(coder aDecoder: NSCoder) { 
     guard let blogName = aDecoder.decodeObject(forKey: "blogName") as? String, 
      let blogStatus1 = aDecoder.decodeObject(forKey: "blogStatus1") as? String, 
      let blogStatus2 = aDecoder.decodeObject(forKey: "blogStatus2") as? String, 
      let blogURL = aDecoder.decodeObject(forKey: "blogURL") as? String, 
      let blogID = aDecoder.decodeObject(forKey: "blogID") as? String, 
      let blogType = aDecoder.decodeObject(forKey: "blogType") as? String, 
      let blogDate = aDecoder.decodeObject(forKey: "blogDate") as? String, 
      let blogPop = aDecoder.decodeObject(forKey: "blogPop") as? String else { 
       print("Error: (Creating Blog Object)") 
       return nil 
     } 
     self.init(name: blogName, status1: blogStatus1, status2: blogStatus2, url: blogURL, id: blogID, type: blogType, date: blogDate, pop: blogPop) 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(blogName, forKey: "blogName") 
     aCoder.encode(blogStatus1, forKey: "blogStatus1") 
     aCoder.encode(blogStatus2, forKey: "blogStatus2") 
     aCoder.encode(blogURL, forKey: "blogURL") 
     aCoder.encode(blogID, forKey: "blogID") 
     aCoder.encode(blogType, forKey: "blogType") 
     aCoder.encode(blogDate, forKey: "blogDate") 
     aCoder.encode(blogPop, forKey: "blogPop") 
    } 
} 

Beachten Sie, dass dieses Problem zu beheben möglicherweise nicht sofort Ihr Problem die ID zeigt, aber es wird Ihnen helfen, wo Sie die Blog Instanz initialisiert richtig

Verwandte Themen