Swift + Magical record + select distinct

2»

Réponses

  • LeChatNoirLeChatNoir Membre, Modérateur

    Ben tiens, un bon exemple d'application de ta méthode de coding (désolé, ça part dans tous les sens...)


     


    Dans ma dernière section, j'ai une mapView sur laquelle je vais mettre des pins  pour situer les topos. Du coup, tout ce code qui va s'occuper de boucler sur les topos et créer des annotations, je le mets dans la TableViewCell de la map ? C'est elle qui sera delegate de la map ? 


     


    J'avoue que j'ai pas l'habitude. J'aurai plutôt laissé ça au viewController principal (celui qui gère la tableView).

  • LeChatNoirLeChatNoir Membre, Modérateur


    Et voilà  !


     


    Tu mets Topo.price en NSDecimalNumber et tu mets quelque chose comme le code d'Apple dans la classe PackDetailHeaderCell, juste avant de l'assigner au bouton.


     


    Mais, à  la place d'utiliser product.priceLocale, tu utiliserais Locale.autoupdatingCurrent.




     


    Oui, mais dans le code d'Apple, il y a un truc qui me manquera, c'est product.priceLocale


    Ca, je ne l'ai que quand j'interroge le store.

  • Joanna CarterJoanna Carter Membre, Modérateur
    janvier 2017 modifié #34


    Dans ma dernière section, j'ai une mapView sur laquelle je vais mettre des pins pour situer les topos. Du coup, tout ce code qui va s'occuper de boucler sur les topos et créer des annotations, je le mets dans la TableViewCell de la map ? C'est elle qui sera delegate de la map ?




    Tu peux utiliser la cellule comme delegate mais il vaut mieux de créer un struct qui implémente le protocole et d'en garder dans un var dans la classe de la cellule.


    Oui, mais dans le code d'Apple, il y a un truc qui me manquera, c'est product.priceLocale
    Ca, je ne l'ai que quand j'interroge le store.




    product.priceLocale renvoie le locale du Store. Tu peux l'oublier et, comme j'ai dit, tu utilises Locale.autoupdatingCurrent.
  • LeChatNoirLeChatNoir Membre, Modérateur


    Tu peux utiliser la cellule comme delegate mais il vaux mieux de créer un struct qui implémente le protocole et d'en garder dans un var dans la classe de la cellule.


     


     


    product.priceLocale renvoie le locale du Store. Tu peux l'oublier et, comme j'ai dit, tu utilises Locale.autoupdatingCurrent.




     


    Génial pour le prix ! Je connaissais pas :)


     


    Un struct qui implémenter le protocole pour la map et qu'on met en var dans la cellule... 


    Tu vois, je trouve ça un peu lourd... Je suis pas bien sûr de l'intérêt...


     


    Je vais délocaliser le code dans la cellule déjà  et je posterai mon code. J'ai une formatrice motivée, alors j'en profite ;)

  • LarmeLarme Membre
    janvier 2017 modifié #36


    Ah :( En fait, Topo est en Objective-C mais le viwController dans lequel je suis est en swift...


     


    Bon ben c'est pas grave, je fais ça du coup :



    let paidFilter = NSPredicate(format:"free=%d",segment)
    region=Topo.mr_findAllSorted(by: "region", ascending: true, with: paidFilter) as! [Topo]!
    filters=Array(Set(region.map{$0.region}))

    Ca marche pareil. C'est moins élégant :( Merci de votre aide !




     


    Il me semble que la grosse différence est où se fait le filtrage (le distinct dans ton cas). Je crois que c'est un moins optimisé que de faire l'unicité dans la requête, car le filtrage est alors fait lors de la recherche (dans la requête SQL-like).


    En bref, si ta BDD a 5k données et que tu n'en veux au final que 5, tu vas toutes les récupérer et après filtrer.


    Bon, dans ton cas, je suppose que tu n'auras pas d'écart aussi important entre le nombre de données totale et celles filtrées, voire de données totale et vu les machines actuelles...


     


     


     


    Concernant la struct/cell, j'aime bien aussi faire de temps en temps [cell fillWithMyCustomObject:(NSCustomClass *)customObject] et ça se chargera de mettre les bonnes données.


    Cependant, en fonction de la réutilisation de cette customClass, la logique des "human readable and friendly data", peut être fait dans cette classe et pas uniquement dans celle de la cell.


    Du coup, je ferais plus dans celle-ci : self.descriptionLabel.text = topo.localizedDescription.


  • LeChatNoirLeChatNoir Membre, Modérateur
    janvier 2017 modifié #37

    Oui effectivement, j'aurai préféré faire fonctionner le distinct et récupéré uniquement une colonne mais bon, je n'ai pas de gros volumes donc ça passe...


     


    Alors comme promis, j'ai adopté la structure de ma nouvelle maitresse (désolé Alf ;)) et je poste mon code. Bon, j'ai fait des trucs pas catholiques je pense avec mes NSDictionary de sites :)


     


    En tous cas, ça commence à  me plaire cette manière de faire par contre, une question me turlupine...


     


    Quand l'utilisateur va ouvrir l'annotation, je vais rajouter un bouton "Infos" et quand il clique dessus, je voudrais faire un performSegue qui se trouve au niveau du ViewController qui héberge la tableView (dans laquelle, j'ai cette map).


     


    Si j'avais mis mon view controller comme delegate de la map, ça aurait été simple. Mais là  ?



    //
    // packMapCell.swift
    // ClimbingAway
    //
    // Created by LeChatNoir on 10/01/2017.
    //
    //

    import UIKit
    import MapKit

    class packMapCell: UITableViewCell, MKMapViewDelegate {

    @IBOutlet weak var packMap: MKMapView!
    var annotations:[Site]!=[]
    var topos: [Topo]?
    {
    didSet
    {
    guard let topos = self.topos else
    {
    return
    }

    for topo in topos {
    let siteInfos=localeDB.sharedSites().object(at: topo.site.intValue) as! [String:Any]

    //Add annotation
    let latitude=siteInfos["latitude"] as! String
    let longitude=siteInfos["longitude"] as! String
    let nom=siteInfos["nom"] as! String

    let siteLocation = CLLocation(latitude:Double(latitude)! , longitude: Double(longitude)!)
    let annot=Site(title: nom,coordinate: siteLocation.coordinate)
    annotations.append(annot)
    }

    packMap.addAnnotations(annotations)
    packMap.showAnnotations(annotations, animated: true)
    }
    }



    override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    packMap.delegate = self

    }

    override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
    }

    }

  • Joanna CarterJoanna Carter Membre, Modérateur
    janvier 2017 modifié #38

    1. Encore tu continues à  commencer les noms des types avec une minuscule  >:(


     


    2. Tu continues à  utiliser les points d'exclamation partout ! Tu risques de tuer les poneys  >:(


     


    3. Tu continues à  serrer le code sans les espaces autour les opérateurs, etc  >:(


     


    4. Tu n'as pas utilisé setSelected mais tu ne l'as pas supprimé  >:(



    class PackMapCell: UITableViewCell
    {
    @IBOutlet weak var packMap: MKMapView!

    let mapViewDelegate = MapViewDelegate()

    var topos: [Topo]?
    {
    didSet
    {
    guard let topos = self.topos else
    {
    return
    }

    var annotations = [Site]()

    for topo in topos
    {
    if let siteInfos = localeDB.sharedSites().object(at: topo.site.intValue) as? [String:Any],
    let latitudeStr = siteInfos["latitude"] as? String,
    let latitude = Double(latitudeStr),
    let longitudeStr = siteInfos["longitude"] as? String,
    let longitude = Double(longitudeStr),
    let nom=siteInfos["nom"] as? String
    {
    let siteLocation = CLLocation(latitude: latitude , longitude: Double(longitude)!)

    let annot = Site(title: nom, coordinate: siteLocation.coordinate)

    annotations.append(annot)
    }
    }

    packMap.addAnnotations(annotations)

    packMap.showAnnotations(annotations, animated: true)
    }
    }

    override func awakeFromNib()
    {
    super.awakeFromNib()

    packMap.delegate = self.mapViewDelegate
    }
    }


    class MapViewDelegate : NSObject, MKMapViewDelegate
    {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
    {
    return MKPinAnnotationView(annotation: annotation, reuseIdentifier: "site")
    }
    }

    C'est pas nécessaire de déclarer un var sur la classe pour les annotations, elles sont récupérables à  tout moment du MapView.


  • LeChatNoirLeChatNoir Membre, Modérateur

    rooo. Désolé, je me suis concentré surtout sur la délocalisation du code dans la tableViewCell.


     


    Merci encore pour ta correction, c'est une mine d'infos pour moi ! Je connaissais pas la syntaxe des if avec virgule !


     


    o:)


  • Joanna CarterJoanna Carter Membre, Modérateur


    Je connaissais pas la syntaxe des if avec virgule !




     


    Ni moi ! Je croyais que c'était seulement pour les "if let" mais, après ton message, j'ai essayé :



    let nom = "Joanna"

    let genie = true

    let age = 22

    if nom == "Joanna",
    genie,
    age == 21
    {
    print(nom)
    }
    else
    {
    print("false")
    }

    C'est pareil que :



    let nom = "Joanna"

    let genie = true

    let age = 22

    if nom == "Joanna" &&
    genie &&
    age == 21
    {
    print(nom)
    }
    else
    {
    print("false")
    }

    ... mais avec une différence très subtile ; avec les virgules, on reçoit un avertissement sur le ligne print(nom) qui dit "Will never be executed". à‰videmment, ça pourrait être utile pour vérifier les conditions où on doit utiliser le concept de &&.

Connectez-vous ou Inscrivez-vous pour répondre.