TableView mit Edit/New/Del View
TableView mit Edit/New/Del View
TableView mit Edit/New/Del View
TableView mit Edit/New/Del View
Vorl19_TableViewChangedEditNewDelete
TableView mit Edit/New/Del View: MainView
Anklicken ViewController im Projektbaum
Klasse Stadt anlegen: Cmd N
TableView mit Edit/New/Del View: MainView
•
Name der Klasse: Stadt
•
SubClass: NSObject
TableView mit Edit/New/Del View: MainView
Speichern auf Festplatte
TableView mit Edit/New/Del View: MainView
Klasse Stadt im Quellcode
Quellcode der Klasse Stadt (1. Version)
TableView mit Edit/New/Del View: MainView
class Stadt: NSObject { var name : String = ""
var bemerkung : String = ""
init(Name name:String, Bemerkung bem:String){
self .name = name
self .bemerkung = bem }
}
class Stadt: NSObject { var name : String = ""
var bemerkung : String = ""
init(Name name:String, Bemerkung bem:String){
self.name = name
self.bemerkung = bem }
public func saveDefault(_ defaults:UserDefaults, _ i:Int) { defaults.set(name,forKey:"name"+String(i))
defaults.set(bemerkung,forKey:"bemerkung"+String(i)) } // saveDefault
public func loadDefault(_ defaults:UserDefaults, _ i:Int) { name = defaults.string(forKey:"name"+String(i))!
bemerkung = defaults.string(forKey:"bemerkung"+String(i))!
} // saveDefault
}
Vollständiger Quellcode der Klasse Stadt
TableView mit Edit/New/Del View
Aktuelle Struktur
Ablauf: Cmd+Shif+L
1. ein horizontalen StackView einfügen
2. ein Label-Element in den ViewController einfügen
•
Text: Städte
3. ein Label-Element in den ViewController einfügen
•
Text: Info
4. ein Button neben dem Label einfügen
•
Text: Edit
5. ein Button neben dem Label einfügen
•
Text: New
6. ein Button neben dem Label einfügen
•
Text: Delete
7. Constraints einbauen (10,10,10, gleiche Breite)
8. ein TableView-Element in den ViewController einfügen
9. Constraint (10,10,10,10)
Städte Edit New Del
Übersicht über die UI-Struktur
Info
Aktuelle Struktur Alle 5 Elemente markiert
Aktuelle Struktur des horizontalen Stackviews
Aktuelles
Aussehen
TableView mit Edit/New/Del View
1. staedte-Array deklarieren und erzeugen
var staedte = [Stadt]()
2. Outlet erzeugen
@IBOutlet var labelRow: UILabel!
@IBOutlet var labelInfo: UILabel!
@IBOutlet var tableview: UITableView!
@IBOutlet var bnEdit: UIButton!
@IBOutlet var bnNew: UIButton!
@IBOutlet var bnDelete: UIButton!
3. Bilder ins Projekt importieren
bilder1.zip
Bildsymbole im Projekt
func setStaedte () {
staedte.append( Stadt(Name: "New York", Bemerkung: "Manhattan") ) staedte.append( Stadt(Name: "Mailand", Bemerkung:"Mailander Scala") )
staedte.append( Stadt(Name: "Rom", Bemerkung: "Vatikan, Michelangelo") ) staedte.append( Stadt(Name: "Moskau", Bemerkung: "Roter Platz") )
staedte.append( Stadt(Name: "Wernigerode", Bemerkung: "HS Harz") ) staedte.append( Stadt(Name: "Hamburg", Bemerkung: "Michel") )
staedte.append( Stadt(Name: "Paris", Bemerkung:"Eifelturm") )
staedte.append( Stadt(Name: "Brüssel", Bemerkung: "Atomium") )
staedte.append( Stadt(Name: "Magdeburg", Bemerkung: "Leere Stadionsplätze") ) staedte.append( Stadt(Name: "Stockhom", Bemerkung: "Nobelpreis") )
staedte.append( Stadt(Name: "München", Bemerkung: "Oktoberfest") ) staedte.append( Stadt(Name: "Lübeck", Bemerkung: "Marzipan") )
staedte.append( Stadt(Name: "Kiel", Bemerkung: "Kieler Woche") )
staedte.append( Stadt(Name: "Amsterdam", Bemerkung: "Grachten") )
staedte.append( Stadt(Name: "Dresden", Bemerkung: "Das grüne Zimmer") ) staedte.append( Stadt(Name: "London", Bemerkung: "Tower") )
staedte.append( Stadt(Name: "San Fransisco", Bemerkung: "Golden Gate Bridge") ) staedte.append( Stadt(Name: "Halberstadt", Bemerkung: "John Cage") )
staedte.append( Stadt(Name: "Pisa", Bemerkung: "Schultest") ) staedte.append( Stadt(Name: "Athen", Bemerkung: "Akropolis ") )
staedte.append( Stadt(Name: "Bilbao", Bemerkung: "Guggenheim-Museum") )
staedte.append( Stadt(Name: "Salzburg", Bemerkung: "Festung Hohensalzburg") ) staedte.append( Stadt(Name: "Rio de Janeiro", Bemerkung: "Zuckerhut") )
}
class ViewController: UIViewController,
UITableViewDelegate, UITableViewDataSource {
1. Delegate eintragen:
TableView mit Edit/New/Del View
func numberOfSections(in tableView: UITableView) -> Int { return 1
}
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int { return staedte.count
}
func numberOfSections(in tableView: UITableView) -> Int { return 1
}
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int { return staedte.count
}
TableView mit Edit/New/Del View
1. UITableViewCellStyle.default:
•
Bild links, Titel rechts
2. UITableViewCellStyle.subtitle:
•
Bild links, Titel rechts, darunter Zusatzinformation 3. UITableViewCellStyle.value1:
•
Bild links, Titel in der Mitte, rechts Zusatzinformation 4. UITableViewCellStyle.value2:
•
Zusatzinformation links, rechts Titel
5. Variablen
•
text
•
detailTextLabel
•
imageView
Arten der UITableViewCellStyle
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell") if cell == nil {
cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
}
let row = (indexPath as NSIndexPath).row let stadt:Stadt = staedte[ row ]
cell?.textLabel!.text = stadt.name
cell?.detailTextLabel!.text=stadt.bemerkung switch (stadt.name.count >> 1) {
case 0:
cell?.imageView!.image = UIImage(named: "Bild1") case 1:
cell?.imageView!.image = UIImage(named: "Bild2") case 2:
cell?.imageView!.image = UIImage(named: "Bild3") default:
cell?.imageView!.image = UIImage(named: "Bild7") }
return cell!
}
Quellcode
Delegate Methode
// SelectecIndexChanged
func tableView(_: UITableView, didSelectRowAt: IndexPath) { bnEdit.isEnabled=true
bnDelete.isEnabled=true
let row = (didSelectRowAt as NSIndexPath).row labelRow.text="row: "+String(row)
}
override func viewDidLoad() { super .viewDidLoad()
setStaedte()
tableview .delegate = self
tableview .dataSource = self
}
Aktueller Stand
1. ein uiLabel-Element in den neuen ViewController einfügen
• Inhalt: Datensatz bearbeiten / löschen / Neuer Datensatz (Fontsize: 25) 2. ein uiLabel-Element in den neuen ViewController einfügen
• Inhalt: Name
3. ein uiTextfield-Element in den neuen ViewController einfügen
• Name: tName als Outlet
4. ein uiLabel-Element in den neuen ViewController einfügen
• Inhalt: Bemerkung
5. ein uiTextView-Element in den neuen ViewController einfügen
• Name: tBemerkung als Outlet 6. uiButton für dem Ok-Schalter
• Text: Ok
7. uiButton für dem Cancel-Schalter
Einfügen eines ViewControllern (Cmd+Shift+L)
Neuer ViewController zum Bearbeiten der Daten
Neuer ViewController
1. Aufruf des Einfüge-Dialogs mit Cmd+N.
2. Auswahl des Symbols „Cocoa Touch Class“.
3. Classname „ChangeValuesViewController“
4. SubClass: „UIViewController“
5. Im „Property Inspector“ des ViewControllers den Namen der Swift- Datei eintragen.
TableView mit Edit/New/Del View
Einfügen einer neuen Quellcode-Datei für den ViewController
Swift-Datei für den neuen ViewController
Swift-Datei für den neuen ViewController
Swift-Datei für den neuen ViewController
Swift-Datei für den neuen ViewController
Verknüpfen des ViewControllers mit der Swift-Datei
Swift-Datei für den neuen ViewController
•
Anklicken des linke Schalters (oben) im ViewController
•
Wechseln zum Property-Menu (Viereck)
•
Auswahl in der ComboBox (runterscollen)
TableView mit Edit/New/Del View
nächste Schritte:
•
Aufruf des ChangeControllers
•
Eintragen der Werte
•
Abfangen der Änderungen
TableView mit Edit/New/Del View
•
Verknüpfen des Schalters „Edit“ zum ViewController
•
Anklicken des Schalters
•
Ctrl-Taste drücken
•
ziehen zum ChangeViewController
•
Menüeintrag: „show“
TableView mit Edit/New/Del View
•
Verknüpfen des Schalters „New“ zum ChangeViewController
•
Menüeintrag: „show“
TableView mit Edit/New/Del View
•
Verknüpfen des Schalters „Delete“ zum ChnageViewController
•
Menüeintrag: „show“
Aktueller Stand des Main.Storyboard
enum für die drei Varianten
Cmd N:
enum für die drei Varianten enum für die drei Varianten
Speichern
enum für die drei Varianten
Attribute und Referenzen des ChangeViewController
Interface / Protokoll:
•
UITextViewDelegate (ChangedEvent für die TextView)
Variablen:
•
var stadt : Stadt?=nil
•
var modus : ChangeMode = ChangeMode.EDIT
Outlets:
•
@IBOutlet var labelTitle: UILabel!
•
@IBOutlet var tName: UITextField!
•
@IBOutlet var tBemerkung: UITextView!
•
@IBOutlet var bnOk: UIButton!
ChangedEvent:
•
tNameEditingChanged
ChangedEvents des ChangeViewController
ChangedEvents des ChangeViewController
@IBAction func tNameEditingChanged(_ sender: AnyObject) { if stadt != nil {
stadt!.name=tName.text!
} }
// Delegate !!!
func textViewDidChange(_ textView: UITextView) { if stadt != nil {
stadt!.bemerkung=tBemerkung.text!
}
}
c
switch (modus) {
case ChangeMode.EDIT:
labelTitle.text = "Datensatz bearbeiten"
case ChangeMode.NEW:
labelTitle.text = "Neuer Datensatz"
case ChangeMode.DELETE:
labelTitle.text = "Datensatz löschen "
default:
labelTitle.text = "ChangeModus ist falsch"
}
if stadt == nil {
bnOk.isEnabled = false // New tName.text = "?"
tBemerkung.text = "?"
}
else {
tName.text = stadt!.name
tBemerkung.text = stadt!.bemerkung }
tBemerkung.delegate=self
Methode, die vor dem Anzeigen des 2. ViewControllers aufgerufen wird
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let button:UIButton = sender as? UIButton {
// Abfrage, welcher Schalter: Übergabe der Stadt if button==bnEdit {
if let indexPath = tableview.indexPathForSelectedRow {
let stadt:Stadt = staedte[(indexPath as NSIndexPath).row]
if let dest = segue.destination as? ChangeValuesViewController { dest.stadt=stadt
dest.modus = ChangeMode.EDIT labelInfo.text=stadt.name
} }
} // edit } / prepare
•
im Main-ViewController:
•
prepare-Methode wird immer aufgerufen, wenn man auf einen
Schalter klickt.
Testen der Übergabe der Daten an den 2. ViewController
ChangeValuesViewController: Rücksprünge !
Man benötigt im HauptViewController zwei Methoden:
// Rücksprung vom ChangeViewController Abbruch
@IBAction func unwindCancel(_ segue:UIStoryboardSegue) { // keine Aktion notwendig
} // unwindToEditViewCancel
// Rücksprung vom ChangeViewController Ok
@IBAction func unwindOk(_ segue:UIStoryboardSegue) {
// holen der neuen Werte und speichern oder löschen
}
Verknüpfen der Schalter mit den unWind-Methoden Schalter anklicken, Ctrl-Taste drücken
ziehen zum Schalter exit
ChangeValuesViewController: Rücksprünge !
Schalter Ok
Schalter Cancel
ChangeValuesViewController: Rücksprünge !
Einbau der Rücksprung-Methode im 2. ViewController
@IBAction override func unwind(
for unwindSegue: UIStoryboardSegue,
towards subsequentVC: UIViewController) { if stadt != nil {
stadt!.name=tName.text!
stadt!.bemerkung=tBemerkung.text!
}
}
Speichern der Änderung im HauptController
@IBAction func unwindOk(_ segue:UIStoryboardSegue) {
if let src = segue.source as? ChangeValuesViewController { if let indexPath = tableview.indexPathForSelectedRow {
switch (src.modus) {
case ChangeMode.EDIT:
let stadt:Stadt = staedte[(indexPath as NSIndexPath).row]
stadt.name = (src.stadt?.name)!
stadt.bemerkung = (src.stadt?.bemerkung)!
labelInfo.text=stadt.name+"!"
tableview.reloadRows(at: [indexPath], with: UITableView.RowAnimation.middle) }
} // if let indexPath = tableview.in } // if let src = segue.source as?
} // unwindOk
Testen des Änderns
Modus New
if button==bnNew {
if let dest = segue.destination as? ChangeValuesViewController { dest.modus = ChangeMode.NEW
}
} // New
Methode:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
Modus New
case ChangeMode.NEW:
let stadt:Stadt = Stadt(Name: "",Bemerkung: "") stadt.name = (src.stadt?.name)!
stadt.bemerkung = (src.stadt?.bemerkung)!
labelInfo.text=stadt.name staedte.append(stadt)
tableview.reloadData()
Methode:
@IBAction func unwindOk(_ segue:UIStoryboardSegue) {
Modus Delete
if button==bnDelete {
if let indexPath = tableview.indexPathForSelectedRow {
let stadt:Stadt = staedte[(indexPath as NSIndexPath).row]
if let dest = segue.destination as? ChangeValuesViewController { dest.stadt=stadt
dest.modus = ChangeMode.DELETE labelInfo.text=stadt.name
} }
}
Methode:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
Modus Delete
case ChangeMode.DELETE:
let index = indexPath.row staedte.remove(at: index) tableview.reloadData() bnEdit.isEnabled=false bnDelete.isEnabled=false
Methode:
@IBAction func unwindOk(_ segue:UIStoryboardSegue) {
Speichern und Laden der Daten (default-Datei)
Prinzip
Klasse StadtDB
•
Methode saveStaedte
•
Speichern der Anzahl der Elemente
•
Speichern der einzelnen Städte
•
Eigenständige Methode in der Klasse
•
Methode loadStaedte
•
Lesen der Anzahl der Elemente
•
Laden der einzelnen Städte
•
Eigenständige Methode in der Klasse
Anlegen der Klasse StaedteDB
cmd N
Anlegen der Klasse StaedteDB
Anlegen der Klasse StaedteDB
Anlegen der Klasse StaedteDB
public func saveStaedte(staedte: Array<Stadt>) {
let defaults = UserDefaults.standard
defaults.set(staedte.count,forKey:"staedteCount") var i:Int=0
for stadt in staedte {
stadt.saveDefault(defaults, i) i+=1
}
} // saveStaedte
Anlegen der Klasse StaedteDB
public func loadStaedte() -> Array<Stadt> { var staedte=[Stadt]()
let defaults = UserDefaults.standard
let n = defaults.integer(forKey:"staedteCount")
for i in 0...n-1 {
let stadt = Stadt(Name: "",Bemerkung: "") stadt.loadDefault(defaults, i)
staedte.append(stadt) }
return staedte
} // loadStaedte
Klasse Stadt
public func saveDefault(_ defaults:UserDefaults, _ i:Int) {
defaults.set(name,forKey:"name"+String(i))
defaults.set(bemerkung,forKey:"bemerkung"+String(i)) } // saveDefault
public func loadDefault(_ defaults:UserDefaults, _ i:Int) {
name = defaults.string(forKey:"name"+String(i))!
bemerkung = defaults.string(forKey:"bemerkung"+String(i))!
} // loadDefault
Swift-Datei Main-ViewController var staedte = [Stadt]()
let staedteDB:StaedteDB = StaedteDB()
override func viewDidLoad() { super .viewDidLoad()
let b=true if (b) {
setStaedte() }
else {
staedte = stadtDB.loadStaedte() }
}
Swift-Datei Main-ViewController
case ChangeMode.EDIT:
let stadt:Stadt = staedte[(indexPath as NSIndexPath).row]
…
staedteDB.saveStaedte(staedte: staedte)
case ChangeMode.NEW:
let stadt:Stadt = Stadt(Name: "",Bemerkung: "")
…
staedteDB.saveStaedte(staedte: staedte)
case ChangeMode.DELETE:
let index = indexPath.row
…
staedteDB.saveStaedte(staedte: staedte)
long press Action
let longPressGestureRecognizer = UILongPressGestureRecognizer(
target: self,
action: #selector(addAnnotation(press:)))
longPressGestureRecognizer.minimumPressDuration = 2.0
tableview.addGestureRecognizer(longPressGestureRecognizer)
long press Action
@objc func addAnnotation(press:UILongPressGestureRecognizer) { if (press.state == .began) {
let touchPoint = longPressGestureRecognizer.location(in: self.view) if let indexPath = tableview.indexPathForRow(at: touchPoint) {
let index = indexPath.row
labelInfo.text = "press: " + String(index) }
} // if (press.state == .began) { }