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")
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 UITableView
s ou section
et item
si vous travaillez avec UICollectionView
s.
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 Int
a
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.
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
}