Lisäksi on otettava huomioon, että alla kuvattu List-rakenne ei
toimi muuttujalajin @ObservedObject kanssa.
Tässä käytetään käyttäjän omissa kansioissa olevia tiedostoja,
joten Xcode:ssa on tämä mahdollistettava Entitlements-osiossa
laittamalla SandBox pois päältä.
Määritellään sarakkeiden taulukko, jossa ensimmäinen arvo on
sarakkeen otsake:
@State var
sarat = [[String]]()
Sijoitetaan sarakkeiden otsakkeet valmiiksi paikoilleen, tässä
esimerkki:
let apus =
[""] // yksi sarake
sarat = Array(repeating: apus, count: 6) // taulukon
kaikki sarakkeet
sarat[0][0] = "idKas"
sarat[1][0] = "Suom_nimi"
sarat[2][0] = "Tiet_nimi"
sarat[3][0] = "Heimo"
sarat[4][0] = "Kpl"
sarat[5][0] = "Lisätiedot"
Tämän jälkeen normaali tietokantakutsu, nyt
"SELECT
idKas, Sunimi, LatSuku, Latlaji, HeiNimi, kpl, KasHuom FROM ..."


Kun pysytään em. ForEach-rakenteessa, niin tein uuden version, jossa tietosisältö on edelleen tavallisessa taulukossa [String], mutta esittämistä varten käytetään Identifiable-muuttujaa:
struct Taulu:
Identifiable
{
var id = UUID()
var sara: [String] // sarakkeen data
var piilo: Bool // onko
piilotettava sarake
}
Näin ForEach-rakenne toimii hyvin, eikä tule konsoliin
varoituksia. Samalla tein malliin seuraavia ominaisuuksia:
- sarakkeiden otsake on erillään, eikä skrollaa taulukon mukana
piiloon
- otsakkeen ja sarakkeen leveys ovat suunnilleen samat, ja ne
toimivat yhtäläisesti, kun ikkunan leveyttä pienentää
- otsaketta klikkaamalla saadaan taulukko lajiteltua ao. sarakkeen
suhteen
- tietojen päivitys taulukossa onnistuu hyvin
Tässä testiprojektin ikkuna:

Taulukon data on muuttujassa:
@State var sisus =
[Taulu]()
ja taulukon esittävä koodi on oheisessa kuvassa (tässä ei ole
otsaketta mukana):

NSTableView:n saaminen SwiftUI-näkymään hoidetaan ns.
wrapper-rakenteen avulla. Siinä on määriteltävä
NSViewControllerRepresentable, Class Coordinator ja kaksi
apufunktiota. Netin ohjeet olivat hyvin sekavat ja Applen doku
liian suppea, mutta löytämiäni tiedonmurusia hyödyntäen ja loput
kokeilemalla sain tehtyä toimivan kokonaisuuden. Hyödyllisin lähde
oli nimimerkki cpahull GitHubissa.
Taulukossa minua kiusasi, että valittuna olevan rivin väri on tummansininen tai keskiharmaa riippuen siitä onko taulukolla focus vai ei. Hoidin tilanteen ohjelmoimalla, että väri on aina sama. Taustaväri järjestetään toimenpiteellä "Subclassing of NSTableRowView":
Tarvitaan delegaatti NSTableViewDelegate ja sille funktio
func
tableView(_ tableView: NSTableView, rowViewForRow row: Int)
-> NSTableRowView?
{
return OmaRowView()
}
class
OmaRowView: NSTableRowView
{
//-------------------------------------------
// Valitulle riville haluttu taustaväri
override func drawSelection(in dirtyRect: NSRect)
{
if self.selectionHighlightStyle != .none
{
let selectionRect =
NSInsetRect(self.bounds, 1.0, 1.0) //, 2.5, 2.5)
let valittu = NSColor(red:
240/255, green: 230/255, blue: 140/255, alpha: 1.0)
valittu.setFill()
let selectionPath =
NSBezierPath.init(roundedRect: selectionRect, xRadius: 0,
yRadius: 0)
selectionPath.fill()
}
}
//-------------------------------------------
// Valitun rivin tekstiväri normaali musta eikä inverted
(valkoinen):
override var isEmphasized: Bool
{
set {}
get { return false }
}
override var selectionHighlightStyle:
NSTableView.SelectionHighlightStyle
{
set {}
get { return .regular }
}
}
Toimivan monipuolisen testiprojektin näyttö on alla. Projektissa
on demottu miten taulukosta saa rivitiedot SwiftUI-puolelle
muokattavaksi ja infona Labeliin. Lisäksi voidaan lajitella, tehdä
uusi kasvi, poistaa rivi sekä tyhjennyksen jälkeen ottaa tiedot
esille siten, että sama kasvi on valittuna kuin viimeksi.
Viestinviejänä SwiftUI:n ja NSTableView:n välillä käytetään kahta
asiaa: sisältö taulukossa on kenttä 'valittu', joka saa arvon "x"
jos rivi on valittuna, sekä muuttujaa 'tilaidkasvi', joka sisältää
valitun rivin arvon idKas. Molemmat ovat @State -muuttujia
SwiftUI-puolella, mutta vain taulukon sisältö nähdään ja voidaan
muokata rajoituksetta sekä SwiftUI- että NSTableView-puolella.
Lisäksi valitun rivin ulkoasua on muutettu siten, että se on sama
okra olipa taulukolla focus tai ei.
Ohjelmoinnin kannalta on merkittävää, että NSTableView:n
delegaattia NSTableViewDataSource
ei voi käyttää wrapperissä tai sen kutsumassa, taulukon
sisältävässä luokassa. Lisäksi on huomattava, että delegaatti
NSTableViewDelegate on wrapperissa, joten sinne tuli yksi
delegaattifunktio ja Subclassing of NSTableRowView.
Tässä kuva sovelluksesta:

Toimivan testisovellukseni Xcode-projekti + docx selityksineen on
ladattavissa täältä.
Yksinkertaisempi demosovellukseni Taulutesti8 on pitkälti
samanlainen kuin edellä. Siinä button 'Näytä' vie valitun rivin
tietoja tekstiboksiin. Se soveltuu hyvin sinne, missä riviä
klikatessa ei tarvitse tapahtua jotain (esim. tietojen kopiointia
tai toisen näkymän avaamista). Valittu rivi on aina okran värinen
mustine teksteineen:
