Visualizzazione di elementi fissi e modificabili in un Elenco sorgenti
-
06-07-2019 - |
Domanda
Sfondo
Sto creando un Elenco sorgenti per la mia applicazione e lo voglio strutturato in modo simile a quello di iTunes, con due tipi di elementi:
- " Fixed " articoli & # 8211; questi non cambiano e non possono essere spostati in & # 8211; in alto
- Elementi modificabili sottostanti, che possono essere modificati dall'utente & # 8211; spostato, rinominato ecc. (nell'esempio di iTunes, come playlist e playlist smart)
Nella mia analogia di iTunes:
(fonte: perspx.com )
Il modo in cui ho strutturato i miei dati finora è il seguente:
- Gli elementi che voglio essere modificabili sono " gruppo " elementi, sotto forma di
Group
Entità di dati principali. - Ogni elemento nell'elenco Sorgente è rappresentato come un oggetto
SourceListItem
normale Objective-C in modo da poter associare ogni elemento a un titolo, un'icona, elementi figlio ecc. - Gli elementi fissi sono attualmente rappresentati dalle istanze
SourceListItem
, archiviate in un array nel mio oggetto controller.
La domanda
Non sono sicuro di come combinare questi due tipi di elementi nell'elenco Sorgente, in modo che gli elementi fissi siano nella parte superiore e sempre lì e non cambino, e gli elementi modificabili siano nella parte inferiore e possono essere spostati e modificato.
Queste sono le idee che mi sono venute finora:
Aggiungi gli elementi fissi al modello di dati di base. Ciò significa che posso creare un'entità per rappresentare gli elementi dell'elenco di origine e posizionare i miei elementi fissi e modificabili in questi casi. Quindi questi possono essere associati alla colonna della tabella Vista struttura con un controller di array / albero. Tuttavia, ciò significa che dovrei creare una nuova entità per rappresentare gli elementi dell'elenco di origine e quindi sincronizzare i
Group
con questo. Dovrei anche avere un modo per creare tutti gli elementi fissi una sola volta, e se accadesse qualcosa a uno dei file di archivio persistenti, gli elementi fissi non sarebbero visualizzati.Unisci gli elementi fissi con gli elementi del gruppo. Mentre entrambi sono memorizzati in array separati, questo potrebbe essere fatto nel controller per la mia finestra quando la Vista struttura richiede i dati (se adottando il protocollo
NSOutlineViewDataSource
, non i bind). Tuttavia, ciò significa che dovrei creare nuoviSourceListItem
per ciascun gruppo nel controller di array (per associare ciascuno con icone e altri attributi), archiviarli e quindi guardare il controller di array di gruppo per le modifiche a rimuovere, aggiungere o modificare le istanzeSourceListItem
quando vengono apportate modifiche ai gruppi.
Qualcuno ha idee migliori su come posso implementarlo?
Vorrei che la mia applicazione fosse compatibile con OS X v10.5, quindi preferirei qualsiasi soluzione che non dipendesse dall'installazione di Snow Leopard.
Soluzione
Sto lavorando a un'app che ha esattamente lo stesso comportamento, ed ecco come lo sto facendo:
Ho 5 entità principali nel mio modello di dati di base:
-
AbstractItem
- un'entità astratta che ha gli attributi comuni a tutti gli elementi, comename
,peso
emodificabili
. Ha anche due relazioni:parent
(relazione one-to conAbstractItem
) echildren
(relazione to-many conAbstractItem
e l'inverso diparent
). -
Group
- Entità figlio concreta diAbstractItem
. -
Cartella
- Entità figlio concreta diAbstractItem
. Aggiunge una relazione molti-a-molti all'entitàItem
di base. -
SmartFolder
- Entità figlio concreta diCartella
. Aggiunge un attributo binariopredicateData
. Sostituisce gli articoli diFolder
" accedente alla relazione per restituire i risultati dell'esecuzione di una richiesta di recupero con il predicato definito dall'attributopredicateData
. -
DefaultFolder
- Entità figlio concreta diSmartFolder
. Aggiunge un attributo stringaidentificatore
.
Per la " Library " elementi della sezione, inserisco oggetti DefaultFolder
e offro loro un identificatore univoco in modo che io possa recuperarli facilmente e differenziarli. Offro anche loro un NSPredicate
che corrisponde a quali elementi
dovrebbero mostrare. Ad esempio, il " Music " DefaultFolder
avrebbe un predicato per recuperare tutti gli elementi musicali, i "Podcast" DefaultFolder
avrebbe un predicato per recuperare tutti gli elementi Podcast, ecc.
Gli elementi a livello di radice (" Library " ;, " Shared " ;, " Store " ;, " Genius " ;, etc) sono tutti elementi Group
con un nil genitore. I gruppi e le cartelle che non possono essere modificati hanno l'attributo
modificabile
impostato su NO
.
Per quanto riguarda effettivamente ottenere queste cose nel tuo outlineView, dovrai implementare tu stesso i protocolli NSOutlineViewDataSource
e NSOutlineViewDelegate
. C'è troppa complessità comportamentale qui per pomparla attraverso un NSTreeController
. Tuttavia, nella mia app, ho ottenuto tutto il comportamento (anche il trascinamento della selezione) in meno di 200 righe di codice (quindi non è così cattivo).
Altri suggerimenti
Non iniettare sciocchezze nel tuo set di dati semplicemente per supportare una vista. Questo non solo va contro il modello di progettazione MVC, ma aggiunge inutili complessità (cioè "più potenziale per i bug") alla parte più importante: la gestione dei dati degli utenti.
Detto questo, l'utilizzo di Bindings in questo particolare scenario è ciò che sta causando così tanto attrito. Perché non rifuggire del tutto dagli attacchi? Sei sulla buona strada, penso, usando il protocollo NSOutlineViewDataSource, ma non sei andato abbastanza lontano. Invece, affidati pienamente a questo protocollo (ancora perfettamente valido e in qualche modo superiore).
Dovresti scambiare essenzialmente la facilità di installazione (e la facilità di notifica delle modifiche) per il pieno controllo sulla struttura ad albero.