I'm trying to create a function to check the Connectivity when the App loads. If a internet connection is detected, the app should download the JSON data and save the array in UserDefaults, then proceed to the UITableView methods. However, if the internet connection is not found, the app should recover the array on USerDefault to populate another array, then proceed to UItableView methods.
The problem I'm facing, is that when the compiler goes trough UserDefault line to be able to save the array, the app crashes immediately. What I'm doing wrong?
Compiler Error:
) for key backupSaved' *** First throw call stack: (0x18257ad8c 0x1817345ec 0x18257ac6c 0x1825b1d08 0x1824e730c 0x1824e5a60 0x1825b2080 0x182515cec 0x1825b2080 0x1825b2304 0x182518d6c 0x182518588 0x182518c54 0x1825bc218 0x1825bf8a0 0x182edaaf4 0x102a794c0 0x102a7452c 0x102e8d314 0x102e45b7c 0x103da11dc 0x103da119c 0x103da5d2c 0x182523070 0x182520bc8 0x182440da8 0x184425020 0x18c45d758 0x102a756b0 0x181ed1fc0) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)
[FIXED]ViewController:
import UIKit
import Kingfisher
import Alamofire
var arrCerveja = [Cerveja]()
var arrBackup = [Cerveja]()
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
//TableView DataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if Connectivity.isConnectedToInternet {
return arrCerveja.count
} else {
return arrBackup.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! TableViewCell
if Connectivity.isConnectedToInternet {
let model = arrCerveja[indexPath.row]
cell.labelName.text = model.name
cell.labelDetail.text = "Teor alcoólico: \(model.abv)"
let resource = ImageResource(downloadURL: URL(string: "\(model.image_url)")!, cacheKey: model.image_url)
cell.imageViewCell.kf.setImage(with: resource, placeholder: UIImage(named: "icons8-hourglass-48"), options: nil, progressBlock: nil, completionHandler: nil)
return cell
} else {
let model = arrBackup[indexPath.row]
cell.labelName.text = model.name
cell.labelDetail.text = "Teor alcoólico: \(model.abv)"
let resource = ImageResource(downloadURL: URL(string: "\(model.image_url)")!, cacheKey: model.image_url)
cell.imageViewCell.kf.setImage(with: resource, placeholder: UIImage(named: "icons8-hourglass-48"), options: nil, progressBlock: nil, completionHandler: nil)
return cell
}
}
//TableView Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if Connectivity.isConnectedToInternet {
performSegue(withIdentifier: "segueId", sender:arrCerveja[indexPath.row])
} else {
performSegue(withIdentifier: "segueId", sender:arrBackup[indexPath.row])
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueId" {
let des = segue.destination as? TableViewDetalhes
//.item possui uma propriedade instanciada na TelaDetalheProdutos
des?.item = (sender as? Cerveja)
//Segue para CollectionView Categorias
}
}
struct Connectivity {
static let sharedInstance = NetworkReachabilityManager()!
static var isConnectedToInternet:Bool {
return self.sharedInstance.isReachable
}
}
override func viewDidAppear(_ animated: Bool) {
if Connectivity.isConnectedToInternet {
print("Connected")
getApiData { (cerveja) in
arrCerveja = cerveja
//Backup
do{
let data = try JSONEncoder().encode(arrCerveja)
UserDefaults.standard.set(data, forKey: "backupSaved")
//
self.tableView.reloadData()
}catch{print(error)
}
}
} else {
print("No Internet")
do{
if let savedData = UserDefaults.standard.value(forKey: "backupSaved") as? Data {
arrBackup = try JSONDecoder().decode([Cerveja].self, from: savedData)
self.tableView.reloadData()
}
}catch{
print(error)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
//SetupNavBarCustom
navigationController?.navigationBar.setupNavigationBar()
}
}
Model:
struct Cerveja:Decodable{
let name:String
let image_url:String
let description:String
let tagline:String
let abv:Double
let ibu:Double?
}
The array should be endcoded to Data before saving , as it's array of custom objects
//
Since now you encode & decode
//
Also I don't vote for saving in userDefaults consider CoreData