In plist (for further use with a cord) I keep a list of exercises from three item, which in turn contain the names of these three complexes and a list of several exercises in each complex. Exercise Complex Description File

import Foundation class Exersise: NSObject { var name: String! var image: String! var exersiseDescript: String! init(name: String, image: String, exersiseDescript: String){ super.init() self.name = name self.image = image self.exersiseDescript = exersiseDescript } static var sectionNames: [String] = [] // НАЗВАНИЕ КОМПЛЕКСА УПРАЖНЕНИЙ, ОТОБРАЖАЕТСЯ В НАЗВАНИИ СЕКЦИЙ ТАБЛИЦЫ static var all: [[Exersise]] = { var allObjects: [[Exersise]] = [] let path = NSBundle.mainBundle().pathForResource("Exersises", ofType: "plist") let objects = try! NSPropertyListSerialization.propertyListWithData(NSData(contentsOfFile: path!)!, options: .MutableContainersAndLeaves, format: nil) as! NSArray for object in objects { sectionNames.append(object["name"] as! String) var subArray: [Exersise] = [] for item in object["items"] as! NSArray { subArray.append(Exersise(name: item["name"] as! String, image: item["image"] as! String, exersiseDescript: item["exersiseDescript"] as! String)) } allObjects.append(subArray) } return allObjects }() } 

The main controller of access to the complex exercises

 import UIKit import StoreKit var buyArray = [0] class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if (NSUserDefaults.standardUserDefaults().objectForKey("Buy") != nil){ buyArray = NSUserDefaults.standardUserDefaults().objectForKey("Buy") as! Array print("buyArray = \(buyArray)") } } @IBAction func firstButton(sender: UIButton) { print("Первый комплекс бесплатен") } @IBAction func SecondButton(sender: UIButton) { print("Куплен второй комплекс") buyArray.append(1) // ДОБАВЛЯЕМ КУПЛЕННЫЕ УПРАЖНЕНИЯ В МАССИВ buyArray print("buyArray = \(buyArray)") NSUserDefaults.standardUserDefaults().setObject(buyArray, forKey: "Buy") } @IBAction func ThirdButton(sender: UIButton) { print("Куплен третий комплекс") buyArray.append(2) // ДОБАВЛЯЕМ КУПЛЕННЫЕ УПРАЖНЕНИЯ В МАССИВ buyArray print("buyArray = \(buyArray)") NSUserDefaults.standardUserDefaults().setObject(buyArray, forKey: "Buy") } 

} In the third controller, we display the acquired exercises, it is here when calling the section name that it gives an error ...

 import UIKit import CoreData class AllExersiseTableViewController: UITableViewController { private var exersises: [[Exersise]] = [] private var selected: Set<NSIndexPath> = [] private var sectionCount = 1 override func viewDidLoad() { super.viewDidLoad() var allBuy = ["ONE", "TWO", "THREE"] var buyForTableView = [String]() if (NSUserDefaults.standardUserDefaults().objectForKey("Buy") != nil){ buyArray = NSUserDefaults.standardUserDefaults().objectForKey("Buy") as! Array } for element in buyArray { buyForTableView.append(allBuy[element]) } print(buyForTableView) if buyForTableView == ["ONE"]{ let index = Exersise.sectionNames.indexOf("ONE")! // Название секции в plist exersises.append(Exersise.all[index]) } else if buyForTableView == ["ONE", "TWO"]{ var index = Exersise.sectionNames.indexOf("ONE")! exersises.append(Exersise.all[index]) index = Exersise.sectionNames.indexOf("TWO")! exersises.append(Exersise.all[index]) } else if buyForTableView == ["ONE", "THREE"]{ var index = Exersise.sectionNames.indexOf("ONE")! exersises.append(Exersise.all[index]) index = Exersise.sectionNames.indexOf("THREE")! exersises.append(Exersise.all[index]) } else if buyForTableView == ["ONE", "TWO", "THREE"] || buyForTableView == ["ONE", "THREE", "TWO"]{ var index = Exersise.sectionNames.indexOf("ONE")! exersises.append(Exersise.all[index]) index = Exersise.sectionNames.indexOf("TWO")! exersises.append(Exersise.all[index]) index = Exersise.sectionNames.indexOf("THREE")! exersises.append(Exersise.all[index]) } } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return exersises.count } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return exersises[section].count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) let object = exersises[indexPath.section][indexPath.row] cell.textLabel?.text = object.name cell.imageView?.image = UIImage(named: object.image) cell.accessoryType = selected.indexOf(indexPath) != nil ? .Checkmark : .None return cell } override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return Exersise.sectionNames[section] } private func addWorkout(name: String) { let manager = CoreDataManager.defaultManager() let workout = NSEntityDescription.insertNewObjectForEntityForName("Workout", inManagedObjectContext: manager.managedObjectContext) as! Workout workout.creationDate = NSDate() workout.name = name workout.items = NSKeyedArchiver.archivedDataWithRootObject(selected) manager.save() } } 

Here is an example error enter image description here

Who cares, the link to the project https://yadi.sk/d/Eh4yTEgiukyYT Thank you all for your help!

Example of incorrect display of sections to the following commentary. enter image description here

  • you have Exersise.sectionNames empty. When you try to force it unwrap (you have a '!' Worth it), you unexpectedly found nil - Max Mikheyenko
  • Already a lot of time I killed at the seemingly not a difficult moment, I broke my brains, but I didn’t finish it. Pliz tell me how to arrange correctly so that Exersise is full ... - Artur Skachkov
  • and where and how do you fill it? - Max Mikheyenko
  • I apologize for not putting the question correctly. How do I properly implement the display of available sections with exercises? - Artur Skachkov September
  • Max, helped more than once on different topics, help pliz solve the problem :( - Artur Skachkov

1 answer 1

The problem with you is that the code that must fill this same array is never called. That's why the nil array is crashing with force unwrap. The easiest way to fill this array is to call the fill function, before using the array.

 _ = Exersise.all 

like this

  • Added, now it works, it is already super, but not completely correct ((When adding a third item, for example, to the shopping array, without adding the second one first, it displays the first and second, and not the first and third, when started. IndexOf does not work? For example, added screen at the end of the question - Artur Skachkov
  • Now I looked closely, it turns out the list in the added section is correct, from the third section. But the name of the section for some reason writes the second, and not the third. I don't understand - Artur Skachkov