2015-07-05 11 views
6

So, si spera, che la classe NSIndexPath si occupi di array con array.NSIndexPath in Swift

ho questo codice:

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. 
    } 


} 

Quello che non capisco come funziona NSIndexPath. Ho letto la documentazione ma è ancora troppo difficile per me capire a questo punto del mio apprendimento come funziona. Come posso sapere che NSIndexPath ha una proprietà di riga? Lattine qualcuno spiegare ogni parte di questa linea per favore:

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

Come si fa a sapere che NSIndexPath Titolo del Corso in questa costante si riferisce al numero di indice 0 whitin indice di array 0 ("iOS App Dev with Swift Essential Training","Simon Allardice")

+1

Cerca "tuple" nella documentazione di Swift. –

+1

Xcode ha alcune funzioni utili per aiutarti a capire il codice che stai guardando. In Xcode, fai Option-click su 'row' nella riga dell'istruzione sopra, e ti dirà di cosa si tratta. Nel pop-up, se si fa clic su "NSIndexPath UIKit Additions" accanto a "Reference", verrà visualizzata la documentazione. – vacawama

risposta

31

Che cosa non capisco come funziona NSIndexPath.

Per iOS, si può pensare di NSIndexPath come una struttura di sola lettura che contiene due Int proprietà section e row se si sta lavorando con UITableView s o section e item se si sta lavorando con UICollectionView s.

Si crea loro con il metodo NSIndexPath:forRow:inSection: di fabbrica:

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

e leggerli accedendo loro proprietà:

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

Come faccio a sapere NSIndexPath ha proprietà di fila?

Xcode ha alcune funzioni utili per aiutarti a capire il codice che stai guardando. In Xcode, , opzione, fai clic su row nella riga dell'istruzione sopra e ti dirà di cosa si tratta. Nel pop-up, se si fa clic su NSIndexPath UIKit Additions accanto a Riferimento, verrà visualizzata la documentazione.

Qualcuno può spiegare ogni parte di questa linea per favore:

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

devCourses è un array di tuple contenenti due valori di tipo String. È possibile vedere questo opzione -clicking su devCourses e mostra [(String, String)]. Se fosse stata una serie di array di String, avrebbe detto [[String]] o [Array<String>] (che è due modi di dire la stessa cosa).

indexPath.row è solo un Int che indica la riga selezionata di tableView.

devCourses[indexPath.row] quindi è la tupla di quell'indice. Ad esempio, se row erano 0, la tupla sarebbe ("iOS App Dev with Swift Essential Training","Simon Allardice").

Infine, è possibile inizializzare due variabili contemporaneamente dichiarandole come una tupla e inizializzandole con una tupla. Per esempio:

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

crea due Int costanti a e b e assegna 3-a e 4-b.

Quindi questa affermazione sta recuperando tupla dalla matrice indicata dal numero intero indexPath.row e creando due variabili, assegnando la prima variabile courseTitle il valore del primo valore nella tupla e assegnando la seconda variabile courseAuthor il valore del secondo valore nella tupla.


Aggiornamento per Swift 3

NSIndexPath esiste ancora in Fondazione, ma quando si lavora con indexPaths in Swift 3, un nuovo tipo di IndexPath è ora utilizzato. Questo tipo è una struttura .

È comunque possibile creare un NSIndexPath a Swift 3, con la seguente sintassi aggiornato, ma non è possibile modificare le proprietà:

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

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

ma si consiglia di utilizzare la nuova struttura di IndexPath invece.

IndexPath viene creato con una sintassi simile:

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

ip2.row = 5 // this works 

È possibile convertire tra IndexPath e NSIndexPath per fusione con 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 

Tutto il cacao e Cocoa Touch API che utilizza indexPaths è stato convertito per utilizzare IndexPath in Swift.

+3

swift3: 'let indexPath = IndexPath (row: someRow, section: someSection)' –

+0

Grazie a @AmrLotfy, ho aggiornato la risposta con le informazioni di Swift 3. – vacawama

4

Leggermente fuori tema, ma mi piacerebbe incoraggiare tutti a utilizzare classi personalizzate per il modello piuttosto che i tipi "primitivi". C'è un piccolo sforzo ma un grande vantaggio.

classe semplice con due proprietà e una descrizione (variabile descrizione è utile durante il debug)

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)"} 
} 

L'array devCourses può essere facilmente mappato per creare i DevCourse istanze con una linea

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) } 

le linee per applicare le proprietà sembrano molto più chiare

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 
}