Aller au contenu

Swift - Programmation d'objects de la librairie XCode (6.4)


Fredo
 Share

Messages recommandés

Salut à tous,

 

Je reviens vers vous avec cette fois un problème Swift lié à la composition de Labels (NSTextField) et de Bouttons (NSButtons) via la programmation.

 

Le code affiché ci-dessous me permet de présenter des labels et un bouton, super, mais, j'aimerai que la position verticale (y) du Label NSMakeRect(x,y,w,v) de "ChampsTexte1"puisse être modifiée.

 

J'ai essayé de créer une Int, que j'appelle ensuite dans NSMakeRect (200,Int,80,20) mais Xcode renvoie une erreur concernant le type de variable (pas accepté).

J'ai essayé tous les types de variable (même Any), impossible de changer ce paramètre (de cette manière).

 

L'idée générale étant de :

- Présenter dans un Label les informations rapportées par "launchctl list" de manière individuelle.

- D'ajouter un 'checkbox' pour chaque fichier.

- Executer "launchctl unload -w ..." ou "launchctl load -w ..." en fonction des 'checkbox'. 

 

J'essaye aussi d'améliorer la présentation des label et buttons mais je me perds dans la forêt d'"api" que les Objets NSTextField et addSubView contiennent.

 

Toute aide sera chaleureusement accueillie!

 

import Cocoa

 

@NSApplicationMain

class AppDelegate: NSObject, NSApplicationDelegate {

 

    @IBOutlet weak var window: NSWindow!

    @IBOutlet weak var nouvLabel: NSView!

    

    

    let ChampsTexte1 = NSTextField()

    let CaseCoche1 = NSButton(frame: NSMakeRect(200,30,80,20))

    let chemin = "/Users/"

    

 

    

    func applicationDidFinishLaunching(aNotification: NSNotification)

    {

    

        CaseCoche1.alignment = NSTextAlignment.CenterTextAlignment

        CaseCoche1.title = "Poursuivre"

        ChampsTexte1.textColor = NSColor.blackColor()

       

        ChampsTexte1.stringValue = chemin

        ChampsTexte1.editable = false

        ChampsTexte1.bezeled = false

        ChampsTexte1.drawsBackground = true

        ChampsTexte1.selectable = false

        ChampsTexte1.frame = NSMakeRect(10,250,400,20)

        

        

        nouvLabel.addSubview(ChampsTexte1)

        nouvLabel.addSubview(CaseCoche1)

        

    }

}

 
Lien vers le commentaire
Partager sur d’autres sites

Swift est beaucoup plus strict que OC sur les typages (il est plus comparable à C++ sur ce point là). NSMakeRect prend des CGFloat, et il n'y a pas de constructeur explicite pour faire un CGFloat à partir d'un Int. Il faut que tu "force" la conversion :

var vY = 42;
 
var rect = NSMakeRect(200, CGFloat(vY), 80, 20)

Par contre si tu as une liste d'éléments à présenter (même avec des checkbox), qui plus est de longueur variable, je te recommande grandement l'utilisation du contrôle qui va bien : NSTableView. Ça prend un peu de temps pour comprendre comment tout fonctionne, mais ça reste relativement simple.

 

P.-S. L'API Cocoa n'a rien à voir avec Xcode (le premier est un API / Framework, le deuxième un IDE) - il est possible d'utiliser Cocoa avec autre chose que Xcode. Et il n'y a pas de "librairie XCode" ;p

Lien vers le commentaire
Partager sur d’autres sites

Merci Zekiller pour les encouragements.

Merci J.P. pour cette réponse très utile.

 

Je me doutais bien que tout ce chipotage (NSTextField,...) ne me mettait pas sur la bonne piste, même si c'est loin d'être inutile.

Je m'en vais explorer NSTableView. 

 

Concernant la "librairie", c'est le terme qui apparait dans l'application même (fenêtre de droite en bas), l'application s'appelle bien XCode (même si "Cocoa" est plus précis, "XCode" n'est pas incorrect).  Je ne parle pas de librairie XCode, mais de librairie d'objets XCode. C'est à dire l'ensemble des "objets" qui apparaissent dans la fenêtre "librairie" de l'application XCode.

Comment le formuler autrement?

Modifié par Fredo
Lien vers le commentaire
Partager sur d’autres sites

J'ai trouvé l'exemple suivant (j'espère que je suis sur la bonne voie) :

 

 

import Cocoa
 
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate
{
    
    @IBOutlet var MonLabel: NSView!
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
 
        func vuetable(vuetable: NSTableView!, viewForTableColumn: NSTableColumn, row: Int) -> NSView
        {
            var cell = vuetable.makeViewWithIdentifier("Liste", owner: self) as! NSTableCellView
            cell.textField!.stringValue = "/Users/"
            cell.frame = NSMakeRect(10,300,400,10)
            return cell
        }
            MonLabel.addSubview(vuetable())
    }

 

Je reçois l'erreur suivante :

Missing argument for parameter #1 in call. Il manque des données, mais lesquelles? Le sais-tu J.P.?

Lien vers le commentaire
Partager sur d’autres sites

Concernant la "librairie", c'est le terme qui apparait dans l'application même (fenêtre de droite en bas), l'application s'appelle bien XCode (même si "Cocoa" est plus précis, "XCode" n'est pas incorrect).  Je ne parle pas de librairie XCode, mais de librairie d'objets XCode. C'est à dire l'ensemble des "objets" qui apparaissent dans la fenêtre "librairie" de l'application XCode.

Comment le formuler autrement?

 

Ah ah oui d'accord. Admettons.

 

La meilleurs formulation reste de parler de Cocoa, des classes Cocoa, ou des contrôles d'AppKit (la "librairie" de Xcode n'est qu'un endroit où ils regroupent les différents contrôles d'AppKit - qui fait lui même partie de Cocoa - pour faciliter la vie des développeurs qui utilisent Xcode).

Lien vers le commentaire
Partager sur d’autres sites

L'exemple que tu donnes est très étrange… Tu as trouvé ça où ?


 


Déjà il semble que la fonction de NSTableViewDelegate "func tableView(_ tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row row: Int) -> NSView?" a été traduite en français… ce qui ne peut pas fonctionner (NSTableView s'attend à la fonction anglaise, pas autre chose).


Ensuite il semble que cette fonction de delegate est réutilisée pour insérer la vue résultante dans "MonLabel". Bon ça c'est… fractalement erroné, si je puis dire ! En gros tu es en train de récupérer une vue que NSTableView construit pour l'ajouter dans une de tes vues à toi.


 


NSTableView est là pour afficher un ensemble d'information, comme tu peux le voir dans la vue en liste dans le Finder, dans iTunes, etc. Cocoa se charge de tout pour toi : tu n'as plus à gérer comment ça se passe. Il s’agit de bien configurer ta NSTableView, et de lui fournir les bonnes informations, et c'est tout.


 


Je te conseille de trouver un autre exemple (je n’ai pas trop le temps de t'en écrire un là, mais on en trouve des dizaines sur le net).


 


Sur quel ligne tu as une erreur ?


 


Sinon une remarque : il faut éviter au maximum d’utiliser les «!» dans Swift, ça casse un peu le modèle des optionals, et la sécurité apportée par ce système. Utilise «?» quand tu peux, et des «if let» pour dépaquer tes optionals. Au risque de me répéter, une lecture, même en diagonale du livre de référence d’Apple sur Swift est utile (il est gratuit sur iBooks).


Lien vers le commentaire
Partager sur d’autres sites

Ah ah oui d'accord. Admettons.

 

La meilleurs formulation reste de parler de Cocoa, des classes Cocoa, ou des contrôles d'AppKit (la "librairie" de Xcode n'est qu'un endroit où ils regroupent les différents contrôles d'AppKit - qui fait lui même partie de Cocoa - pour faciliter la vie des développeurs qui utilisent Xcode).

 

D'accord mais comme c'est plutôt un sujet dédié aux débutants, mieux vaux garder le titre actuel.

 

 

A ce sujet (au sujet du sujet), j'ai trouvé une autre manière, très différente de la précédente, d'utiliser NSTableView, la voici :

 

import Cocoa

 

class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate

{

    

    @IBOutlet var MonLabel: NSView!

    

    override func viewDidLoad()

    {

        super.viewDidLoad()

        // Do any additional setup after loading the view.

        let tableContainer = NSScrollView(frame:NSMakeRect(10, 10, 380, 400))

        let tableView = NSTableView(frame:NSMakeRect(0, 0, 364, 200))

        let column1 = NSTableColumn(identifier: "Col1")

        let column2 = NSTableColumn(identifier: "Col2")

        column1.width = 252

        column2.width = 198

        tableView.addTableColumn(column1)

        tableView.addTableColumn(column2)

        tableView.setDelegate(self)

        tableView.setDataSource(self)

        tableView.reloadData()

        tableContainer.documentView = tableView

        tableContainer.hasVerticalScroller = true

       MonLabel.addSubview(tableContainer)

    }

Cet exemple fonctionne sans erreur, je m'en vais le triturer.
Lien vers le commentaire
Partager sur d’autres sites

Je me suis trompé, je reçois bien une erreur d'implémentation manquante.

La solution se trouve sans doute dans l'assemblage des deux exemples.

Il semblerait qu'un NSScrollView soit obligatoire afin de faire apparaître les colonnes.

Lien vers le commentaire
Partager sur d’autres sites

Je recommence à zéro, en partant de l'exemple suivant :

 

http://www.raywenderlich.com/87002/getting-started-with-os-x-and-swift-tutorial-part-1

 

Il est complexe mais très proche de ce que j'ai besoin.

Il implique la création d'un fichier ViewController.xib et d'un autres au format .swift.

Ensuite le ViewController est configuré et la fonction est appelée, le tout dans AppDelegate.

Est-ce compatible avec mes projets?

Lien vers le commentaire
Partager sur d’autres sites

"D'accord mais comme c'est plutôt un sujet dédié aux débutants, mieux vaux garder le titre actuel."

De mon point de vue, les débutants ont besoin de précision dès le début, sinon ils finissent par se planter parce qu'ils ont créé un schéma mental approximatif, voir erroné.

 

Pour ce qui est de ce nouvel exemple : oui, ça me semble bien plus sérieux que les deux exemples précédant. C'est pas tout à fait ce que tu veux (va falloir mettre des checkbox à la place des images), mais déjà, ça semble beaucoup plus juste et viable !

Lien vers le commentaire
Partager sur d’autres sites

Voilà, je ne suis plus très loin du résultat espéré.

 

La seule chose que je n'arrive pas à faire, c'est de récupérer la valeur des champs de la deuxième colonne (les cases cochées, ou non).

J'ai essayé diverses méthodes mais sans succès. Je ne sais s'il faut créer une nouvelle fonction ou placer l'action dans la fonction existante, NSTableView ou NSTableCellView,...

 

Le projet se trouve en attachement, pour ceux qui veulent jeter un oeil.

NSTableView - Fredo.zip

Modifié par Fredo
Lien vers le commentaire
Partager sur d’autres sites

Voilà ce que je tente pour l'instant (sans grand succès) afin de récupérer le nom des objets dont les cases sont cochées.

Je l'ai adapté d'un script Objective-c qui est censé faire exactement cela. "var etat..." me semble assez bizarrement construit.

 

 

 

    var objets: NSMutableArray! = NSMutableArray()

    var etat: NSMutableArray = [1,0,1,nilHandleErr]

 

 

...

 

 

 

func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject?

    {

        if tableColumn?.identifier == "CaseACocher"

        {

            return self.objets.objectAtIndex(row)

            

        }

        

        if tableColumn?.identifier == "CaseACocher"

        {

            return self.etat.objectAtIndex(row)

            

        }

        return 0

    }

    

    

    

    func tableView(tableView: NSTableView, setObjectValue object: AnyObject?, forTableColumn tableColumn: NSTableColumn?, row: Int)

    {

        etat.replaceObjectAtIndex(row, withObject: value()!)

        tableView.reloadData()

       

        

    }

 

Résultat, rien ne se passe dans la console lorsque j'enclenche un "Check Box".

Lien vers le commentaire
Partager sur d’autres sites

Could not cast value of type '__NSCFString' (0x7fff7c2c3718) to 'NSMutableDictionary' (0x7fff7c2c4500).


 


 

func tableView(tableView: NSTableView!, objectValueForTableColumn tableColumn: NSTableColumn!, row: Int) -> AnyObject!

    {


        let test = objets[row] as! NSMutableDictionary


        


        if tableColumn!.identifier == "CaseACocher"


        {


            


            return test[tableColumn.identifier] as? Int!


            


        }


        return test


    }


    


    


    func tableView(tableView: NSTableView, setObjectValue object: AnyObject?, forTableColumn tableColumn: NSTableColumn?, row: Int)


    {


        objets[row].setObject(object!, forKey: (tableColumn?.identifier)!)


        


    }


 

La variable "objets" est du type NSMutableArray. 

Lien vers le commentaire
Partager sur d’autres sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

Chargement
 Share

×
×
  • Créer...