TableView Cell UISwitch Autolayout

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • TableView Cell UISwitch Autolayout

    Hey zusammen,

    ein neuer Tag ein neues Problem oder eher eine Frage, ob etwas generell möglich ist.

    Es geht darum, ich habe ein TableView mit mehreren Zellen. Nun würde ich eigentlich im Storyboard die Items der Zelle hinzufügen (Label, Switch ect.).

    Da ich das ganze aber dynamisch befüllen lasse, möchte ich die Items per Programmcode hinzufügen.

    Bisher sieht das ganze so aus:

    Quellcode

    1. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    2. let cell = UITableViewCell()
    3. // LABEL 1
    4. let label = UILabel(frame: CGRect(x:70, y:0, width:200, height:50))
    5. label.text = datastructarray[indexPath.row].name
    6. label.font = UIFont(name: label.font.fontName, size: 15)
    7. cell.addSubview(label)
    8. // IMAGE
    9. let imageName = "icon.png"
    10. let image = UIImage(named: imageName)
    11. let imageView = UIImageView(image: image!)
    12. imageView.frame = CGRect(x: 18, y: 15, width: 40, height: 40)
    13. cell.addSubview(imageView)
    14. // LABEL 2
    15. let emaillabel = UILabel(frame: CGRect(x:70, y:25, width:200, height:50))
    16. emaillabel.text = datastructarray[indexPath.row].email
    17. emaillabel.textColor = UIColor(red: (178/255.0), green: (187/255.0), blue: (187/255.0), alpha: 1.0)
    18. emaillabel.font = UIFont(name: label.font.fontName, size: 13)
    19. cell.addSubview(emaillabel)
    20. // SWITCH
    21. let switchDemo = UISwitch(frame:CGRectMake(300, 25, 0, 0));
    22. switchDemo.on = true
    23. switchDemo.setOn(false, animated: false);
    24. switchDemo.addTarget(self, action: "switchValueDidChange:", forControlEvents: .ValueChanged);
    25. cell.addSubview(switchDemo);
    26. cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
    27. return cell
    28. }
    Alles anzeigen

    Alles klappt wunderbar, in den Zellen ist jeweils vorne ein kleines Icon rechts daneben ein Label, darunter noch ein Label und rechts ein UISwitch.

    Nun wechsele ich vom Simulator Iphone6 auf Iphone4s und tja das wars mit dem "Wunderbar".

    [Blockierte Grafik: http://fs5.directupload.net/images/150925/p5xxdxpg.jpg]

    Wie man auf dem Bild erkennen kann, sind die UISwitches (rechts) aus dem Bild raus. Das liegt natürlich an dieser Zeile Code:

    Quellcode

    1. let switchDemo = UISwitch(frame:CGRectMake(300, 25, 0, 0));
    Jetzt zu meiner Frage, gibt es eine Möglichkeit (Storyboard aussen vor) , z.B. prozentuale statt feste Werte für die X & Y Achse zu setzen?


    Ich bin gespannt ob ihr schon ähnliche Fallen überwunden habt :D

    Danke euch !
  • Michael schrieb:

    Warum mach ihr euch das Leben eigentlich selbst so schwer? ?(

    Prozentuale Angaben gibt es nicht. Du kannst aber einfach entsprechende Autolayout Contstaints im Code setzen.

    Mit diesem Code hebelt du übrigens die Wiederverwendung von Zellen aus. D.h. dein Speicherverbrauch wird unnötig hoch.
    Ja das wüsste ich auch zu gerne :D

    Manchmal macht man sich Dinge schwer, bis jemand kommt, der es bereits anders gelernt hat und siehe da es geht auch anders.

    Zumindest wohlmöglich, denn ich hab keine Ahnung wie ich das anstellen soll. Ich wusste noch gar nicht das man Autolayout Constraints im Code setzen kann?

    Was genau meinst du damit "Mit diesem Code hebelt du übrigens die Wiederverwendung von Zellen aus. D.h. dein Speicherverbrauch wird unnötig hoch." ?
  • DKCode schrieb:

    Manchmal macht man sich Dinge schwer, bis jemand kommt, der es bereits anders gelernt hat und siehe da es geht auch anders.
    Mit schwer machen meine ich vor allem, warum alles im Code erzeugen, wenn man das auch im Interface Editor machen kann?

    DKCode schrieb:

    Ich wusste noch gar nicht das man Autolayout Constraints im Code setzen kann?
    Alles was im Interface Editor möglich ist, ist auch per Code möglich. Der Interface Editor führt quasi entsprechenden Code schon mal vorab aus und archiviert das Ergebnis dann in Storyboards oder .xib-Dateien.
    Constraints im Code setzen ist hier beschrieben.

    DKCode schrieb:

    Was genau meinst du damit "Mit diesem Code hebelt du übrigens die Wiederverwendung von Zellen aus. D.h. dein Speicherverbrauch wird unnötig hoch." ?
    Dein Code erzeugt für jeden angefragten IndexPath immer eine neue Zelle. UITableView bietet aber einen Mechanismus, durch den einmal erzeugte Zellen wiederverwendet werden. Eine Zelle, die zum Beispiel nach oben aus dem sichtbaren Bereich heraus scrollt, kann dann unten für einen anderen IndexPath wieder verwendet werden, ohne sie komplett neu erzeugen zu müssen. Man braucht dann nur den Inhalt auf die Werte des angefragten IndexPath setzen.
  • Ohne hier wieder der Buhmann sein zu wollen aber das lernt man alles wenn man sich einfach mal die TableView Tutorials von Apple durchließt

    Ich glaube das ist das zweite oder dritte Kapitel damals gewesen in dem Beginner Guide.
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Michael schrieb:

    Mit schwer machen meine ich vor allem, warum alles im Code erzeugen, wenn man das auch im Interface Editor machen kann?
    weil der InterfaceBuilder/Storyboard einfach wirklich nervt. Gründe hab ich hier irgendwann schon mal ins Forum geschrieben.
    als ich mit iOS angefangen habe konnte man zusätzlich nicht alles was man mit den Views machen kann im iB machen sondern musste immer zusätzlich Sachen im Code machen
    und für einen Anfänger ist es recht verwirrend: Mmmh, hier pack ich die View hinzu, position mach auch hier, das Flag kann ich hier nicht setzen, das muss ich im Code machen, aber das wiederrum kann ich im IB machen

    damit ist man vielleicht schneller zum Start ein paar Views in die ViewController zu werfen, bei der wirklichen Arbeit damit wenn ein Projekt man etwas größer geworden ist, empfinde ich den IB/Storyboard aber nur als hinderlich
    Ich weiß nicht immer wovon ich rede aber ich weiß das ich Recht habe. :saint:
  • Michael schrieb:

    DKCode schrieb:

    Manchmal macht man sich Dinge schwer, bis jemand kommt, der es bereits anders gelernt hat und siehe da es geht auch anders.
    Mit schwer machen meine ich vor allem, warum alles im Code erzeugen, wenn man das auch im Interface Editor machen kann?

    DKCode schrieb:

    Ich wusste noch gar nicht das man Autolayout Constraints im Code setzen kann?
    Alles was im Interface Editor möglich ist, ist auch per Code möglich. Der Interface Editor führt quasi entsprechenden Code schon mal vorab aus und archiviert das Ergebnis dann in Storyboards oder .xib-Dateien.Constraints im Code setzen ist hier beschrieben.

    DKCode schrieb:

    Was genau meinst du damit "Mit diesem Code hebelt du übrigens die Wiederverwendung von Zellen aus. D.h. dein Speicherverbrauch wird unnötig hoch." ?
    Dein Code erzeugt für jeden angefragten IndexPath immer eine neue Zelle. UITableView bietet aber einen Mechanismus, durch den einmal erzeugte Zellen wiederverwendet werden. Eine Zelle, die zum Beispiel nach oben aus dem sichtbaren Bereich heraus scrollt, kann dann unten für einen anderen IndexPath wieder verwendet werden, ohne sie komplett neu erzeugen zu müssen. Man braucht dann nur den Inhalt auf die Werte des angefragten IndexPath setzen.
    Weil ich bisher im Interface Editor massig Probleme mit richtigem Positionieren der einzelnen Elemente hatte.
    Das erinnert mich an die Anfangszeit der Webentwicklung schön über Dreamweaver Layouts per Drag6Drop zusammengeklickt.
    Das Resultat mehr als bescheiden aber funktional. Bis man dann irgendwann verstanden hat, wie das alles über Programmcode
    erzeugt werden kann und das es dann einfacher, schneller und tausendfach schicker aussieht.

    Ich suche jetzt schon eine ganze Weile nach dem von dir beschriebenen Mechanismus zum Thema "gleiche Zelle wiederverwenden". Aber ich finde dazu irgendwie nix.
    Vielleicht überlese ich das ganze auch gekonnt, da mir irgendein Ablauf nicht ganz klar ist und ich somit gar nicht weiß, wo genau die gleiche Zelle im Code genutzt werden könnte.


    Thallius schrieb:

    Ohne hier wieder der Buhmann sein zu wollen aber das lernt man alles wenn man sich einfach mal die TableView Tutorials von Apple durchließt

    Ich glaube das ist das zweite oder dritte Kapitel damals gewesen in dem Beginner Guide.

    Alles gut, ist ja richtig wenn man mich auf solche Dinge hinweist. :thumbsup: Aber bitte mit einem Verweis auf das besagte Tutorial, denn wie oben schon erwähnt finde ich da leider nichts.

    macmoonshine schrieb:

    Sehe ich ähnlich. Der Code im ersten Beitrag zeigt, dass sich der OP wenig mit dem Konzepten des Tableviews vertraut gemacht hat. Insbesondere die Wiederverwendung von Zellen findet sich in jedem Tutorial.
    Ich weiß nur das was StackOverflow oder aber Tutorial-Blogs mir gezeigt haben und in keinem der Tutorials wurden Cells leider wiederverwendet.
    Hätte ich das gewusst, bzw. wüsste ich wie das funktioniert, dann hätte ich es bereits so umsetzt.

    Ich hab das ganze jetzt so umgeschrieben:


    Quellcode

    1. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    2. //let cell = UITableViewCell()
    3. let cellIdentifier = "myCell"
    4. let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! myCells
    5. // LABEL 1
    6. let label = UILabel(frame: CGRect(x:70, y:0, width:200, height:50))
    7. label.text = datastructarray[indexPath.row].name
    8. label.font = UIFont(name: label.font.fontName, size: 15)
    9. cell.addSubview(label)
    10. // IMAGE
    11. let imageName = "icon.png"
    12. let image = UIImage(named: imageName)
    13. let imageView = UIImageView(image: image!)
    14. imageView.frame = CGRect(x: 18, y: 15, width: 40, height: 40)
    15. cell.addSubview(imageView)
    16. // LABEL 2
    17. let emaillabel = UILabel(frame: CGRect(x:70, y:25, width:200, height:50))
    18. emaillabel.text = datastructarray[indexPath.row].email
    19. emaillabel.textColor = UIColor(red: (178/255.0), green: (187/255.0), blue: (187/255.0), alpha: 1.0)
    20. emaillabel.font = UIFont(name: label.font.fontName, size: 13)
    21. cell.addSubview(emaillabel)
    22. // SWITCH
    23. let switchDemo = UISwitch(frame:CGRectMake(300, 25, 0, 0));
    24. switchDemo.on = true
    25. switchDemo.setOn(false, animated: false);
    26. switchDemo.addTarget(self, action: "switchValueDidChange:", forControlEvents: .ValueChanged);
    27. cell.addSubview(switchDemo);
    28. //cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
    29. return cell
    30. }
    Alles anzeigen
    Ist das richtig oder müssen auch alle Elemente ausgelagert werden?

    Ich hatte das versucht, aber bei Codezeilen wie: "label.font = UIFont(name: label.font.fontName, size: 13)" bekomme ich ein Error: expeced declaration.

    Was nun?