web-dev-qa-db-fra.com

NSIndexPath dans Swift

Je sais, espérons-le, que la classe NSIndexPath traite les tableaux qui ont des tableaux.

J'ai ce code:

import UIKit

class ViewController: UIViewController, UITableViewDataSource {

    let devCourses = [
        ("iOS App Dev with Swift Essential Training","Simon Allardice"),
        ("iOS 8 SDK New Features","Lee Brimelow"),
        ("Data Visualization with D3.js","Ray Villalobos"),
        ("Swift Essential Training","Simon Allardice"),
        ("Up and Running with AngularJS","Ray Villalobos"),
        ("MySQL Essential Training","Bill Weinman"),
        ("Building Adaptive Android Apps with Fragments","David Gassner"),
        ("Advanced Unity 3D Game Programming","Michael House"),
        ("Up and Running with Ubuntu Desktop Linux","Scott Simpson"),
        ("Up and Running with C","Dan Gookin") ]

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return devCourses.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var cell = UITableViewCell()

        let (courseTitle, courseAuthor) = devCourses[indexPath.row]
        cell.textLabel?.text = courseTitle

        return cell
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Ce que je ne comprends pas comment fonctionne NSIndexPath. J'ai lu la documentation mais est-il encore trop difficile pour moi de comprendre à ce stade de mon apprentissage comment cela fonctionne. Comment puis-je savoir que NSIndexPath a une propriété de ligne? Quelqu'un peut-il expliquer chaque partie de cette ligne s'il vous plaît:

let (courseTitle, courseAuthor) = devCourses[indexPath.row]

Comment NSIndexPath sait-il que courseTitle dans cette constante fait référence à l'index numéro 0 dans l'index du tableau 0 ("iOS App Dev with Swift Essential Training","Simon Allardice")

8
Antonija

Ce que je ne comprends pas comment fonctionne NSIndexPath.

Pour iOS, vous pouvez considérer NSIndexPath comme une structure en lecture seule contenant deux Int propriétés section et row si vous travaillez avec UITableViews ou section et item si vous travaillez avec UICollectionViews.

Vous les créez avec la méthode d'usine NSIndexPath:forRow:inSection::

let indexPath = NSIndexPath(forRow: 1, inSection: 0)

et lisez-les en accédant à leurs propriétés:

print("row is \(indexPath.row)")

Comment puis-je savoir que NSIndexPath a une propriété de ligne?

Xcode a quelques fonctionnalités intéressantes pour vous aider à comprendre le code que vous regardez. Dans Xcode, Option-cliquez sur row dans la ligne d'instruction ci-dessus, et il vous dira de quoi il s'agit. Dans la fenêtre contextuelle, si vous cliquez sur Ajouts NSIndexPath UIKit à côté de Référence , il affichera la documentation.

Quelqu'un peut-il expliquer chaque partie de cette ligne s'il vous plaît:

let (courseTitle, courseAuthor) = devCourses[indexPath.row]

devCourses est un tableau de tuples contenant deux valeurs de type String. Vous pouvez le voir en option-cliquer sur devCourses et il affiche [(String, String)]. S'il avait été un tableau de tableau de String il aurait dit [[String]] Ou [Array<String>] (Ce qui est deux façons de dire la même chose).

indexPath.row Est juste un Int indiquant la ligne sélectionnée du tableView.

devCourses[indexPath.row] Est alors le Tuple à cet index. Par exemple, si le row était 0, Alors le Tuple serait ("iOS App Dev with Swift Essential Training","Simon Allardice").

Enfin, vous pouvez initialiser deux variables simultanément en les déclarant comme un tuple et en les initialisant avec un tuple. Par exemple:

let (a, b) = (3, 4)

crée deux constantes Inta et b et affecte 3 à a et 4 à b.

Cette instruction récupère donc le Tuple à partir du tableau indiqué par l'entier indexPath.row Et crée deux variables, affectant à la première variable courseTitle la valeur de la première valeur dans le Tuple et affectant la deuxième variable courseAuthor la valeur de la deuxième valeur du Tuple.


Mise à jour pour Swift

NSIndexPath existe toujours dans Foundation , mais lorsque vous travaillez avec indexPaths dans Swift, un nouveau type IndexPath est maintenant utilisé. Ce type est une structure .

Vous pouvez toujours créer un NSIndexPath dans Swift 3, avec la syntaxe mise à jour suivante, mais vous ne pouvez pas modifier les propriétés:

var ip = NSIndexPath(row: 0, section: 0)

ip.row = 5    // Cannot assign to property: 'row' is a get-only property

mais vous devez utiliser à la place la nouvelle structure IndexPath.

IndexPath est créé avec une syntaxe similaire:

var ip2 = IndexPath(row: 0, section: 0)

ip2.row = 5   // this works

Vous pouvez convertir entre IndexPath et NSIndexPath en transtypant avec as:

let ip = NSIndexPath(row: 0, section: 0)
let ip2 = ip as IndexPath     // convert to IndexPath
let ip3 = ip2 as NSIndexPath  // convert back to NSIndexPath

Toutes les API Cocoa et Cocoa Touch qui utilisent indexPaths ont été converties pour utiliser IndexPath dans Swift.

36
vacawama

Légèrement hors sujet, mais j'aimerais encourager tout le monde à utiliser des classes personnalisées pour le modèle plutôt que des types "primitifs". Il y a un petit effort mais un gros avantage.

Classe simple avec deux propriétés et une description (la variable de description est utile lors du débogage)

class DevCourse : Printable {

  var author : String
  var title : String

  init(author : String, title : String) {
    self.author = author
    self.title = title
  }

  var description : String { return "DevCourse \(title) by \(author)"}
}

Le tableau devCourses peut être facilement mappé pour créer les instances DevCourse avec une seule ligne

  let rawDevCourses = [
    ("iOS App Dev with Swift Essential Training","Simon Allardice"),
    ("iOS 8 SDK New Features","Lee Brimelow"),
    ("Data Visualization with D3.js","Ray Villalobos"),
    ("Swift Essential Training","Simon Allardice"),
    ("Up and Running with AngularJS","Ray Villalobos"),
    ("MySQL Essential Training","Bill Weinman"),
    ("Building Adaptive Android Apps with Fragments","David Gassner"),
    ("Advanced Unity 3D Game Programming","Michael House"),
    ("Up and Running with Ubuntu Desktop Linux","Scott Simpson"),
    ("Up and Running with C","Dan Gookin") ]

let devCourses = rawDevCourses.map { DevCourse(author: $0.1, title: $0.0) }

les lignes pour appliquer les propriétés semblent beaucoup plus claires

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("MyIdentifier", forIndexPath: indexPath) as! UITableViewCell

    let course = devCourses[indexPath.row]
    cell.textLabel?.text = course.title

    return cell
}
6
vadian