Je veux sous UIView
- classer et afficher une connexion comme une vue. J'ai créé ceci dans Objective-C, mais maintenant je veux le porter sur Swift. Je n'utilise pas de storyboards, donc je crée toute mon interface utilisateur en code.
Mais le premier problème est que je dois mettre en œuvre initWithCoder
. Je lui ai donné une implémentation par défaut car elle ne sera pas appelée. Maintenant, lorsque je lance le programme, il plante, car je dois également l'implémenter initWithFrame
. Maintenant j'ai ceci:
override init() {
super.init()
println("Default init")
}
override init(frame: CGRect) {
super.init(frame: frame)
println("Frame init")
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("Coder init")
}
Ma question est: où dois-je créer mon champ de texte, etc.
CGRectZero
je pense qu'il est recommandé d'utiliserCGRect.zeroRect
.C'est plus simple.
la source
Exemple de sous-classe UIView personnalisée
Je crée généralement des applications iOS sans utiliser de storyboards ou de pointes. Je vais partager quelques techniques que j'ai apprises pour répondre à vos questions.
Masquer les
init
méthodes indésirablesMa première suggestion est de déclarer une base
UIView
pour masquer les initialiseurs indésirables. J'ai discuté de cette approche en détail dans ma réponse à "Comment masquer les initialiseurs spécifiques au storyboard et à la pointe dans les sous-classes de l'interface utilisateur" . Remarque: cette approche suppose que vous n'utiliserez pasBaseView
ou ses descendants dans les storyboards ou les nibs, car cela provoquera intentionnellement le blocage de l'application.Votre sous-classe UIView personnalisée doit hériter de
BaseView
. Il doit appeler super.init () dans son initialiseur. Il n'a pas besoin d'être mis en œuvreinit(coder:)
. Ceci est démontré dans l'exemple ci-dessous.Ajout d'un UITextField
Je crée des propriétés stockées pour les sous-vues référencées en dehors de la
init
méthode. Je le ferais généralement pour un UITextField. Je préfère subviews de instancier au sein de la déclaration de la propriété sous - vue comme ceci:let textField = UITextField()
.UITextField ne sera visible que si vous l'ajoutez à la liste de sous-vues de la vue personnalisée en appelant
addSubview(_:)
. Ceci est démontré dans l'exemple ci-dessous.Disposition programmatique sans disposition automatique
UITextField ne sera visible que si vous définissez sa taille et sa position. Je fais souvent la mise en page dans le code (sans utiliser la mise en page automatique) dans la méthode layoutSubviews .
layoutSubviews()
est appelé initialement et chaque fois qu'un événement de redimensionnement se produit. Cela permet d'ajuster la disposition en fonction de la taille de CustomView. Par exemple, si CustomView apparaît sur toute la largeur sur différentes tailles d'iPhones et d'iPad et s'ajuste pour la rotation, il doit s'adapter à de nombreuses tailles initiales et se redimensionner dynamiquement.Vous pouvez vous référer à
frame.height
et à l'frame.width
intérieurlayoutSubviews()
pour obtenir les dimensions de CustomView à titre de référence. Ceci est démontré dans l'exemple ci-dessous.Exemple de sous-classe UIView
Une sous-classe UIView personnalisée contenant un UITextField qui n'a pas besoin d'être implémenté
init?(coder:)
.Disposition programmatique avec disposition automatique
Vous pouvez également implémenter la disposition à l'aide de la disposition automatique dans le code. Comme je ne le fais pas souvent, je ne montrerai pas d'exemple. Vous pouvez trouver des exemples de mise en œuvre de la disposition automatique dans le code sur Stack Overflow et ailleurs sur Internet.
Cadres de mise en page programmatiques
Il existe des frameworks open source qui implémentent la mise en page dans le code. Un qui m'intéresse mais que je n'ai pas essayé est LayoutKit . Il a été rédigé par l'équipe de développement sur LinkedIn. Depuis le référentiel Github: "LinkedIn a créé LayoutKit car nous avons constaté que la mise en page automatique n'est pas assez performante pour les hiérarchies de vues complexes dans les vues déroulantes."
Pourquoi mettre
fatalError
eninit(coder:)
Lors de la création de sous-classes UIView qui ne seront jamais utilisées dans un storyboard ou une nib, vous pouvez introduire des initialiseurs avec des paramètres et des exigences d'initialisation différents qui n'ont pas pu être appelés par la
init(coder:)
méthode. Si vous n'avez pas échoué à init (coder :) avec afatalError
, cela pourrait entraîner des problèmes très déroutants sur toute la ligne en cas d'utilisation accidentelle dans un storyboard / nib. FatalError affirme ces intentions.Si vous souhaitez exécuter du code lorsque la sous-classe est créée, qu'elle soit créée dans le code ou dans un storyboard / nib, vous pouvez faire quelque chose comme ce qui suit (basé sur la réponse de Jeff Gu Kang )
la source
fatalError
vous interdisez d'initier cette vue avec des fichiers xibfatalError
intérieur de la méthode dealloc et dites-nous que cela ne fonctionne pas parce que cette classe devrait être un singleton. Si vous préférez créer des éléments d'interface utilisateur dans le code, vous ne devez pas interdire manuellement toutes les autres méthodes. Enfin la question est de savoir comment créer "par programmation sans storyboards" mais les xibs / nibs ne sont pas mentionnés. Dans mon cas, je dois créer un tableau de cellules avec + xib par programme et les transmettreDropDownMenuKit
et cette façon ne fonctionne pas car l'auteur de cette bibliothèque interdit aussi les xib.Il est important que votre UIView puisse être créé par le constructeur d'interface / les storyboards ou à partir du code. Je trouve utile d'avoir une
setup
méthode pour réduire la duplication de tout code de configuration. par exemplela source
Swift 4.0, si vous souhaitez utiliser la vue à partir d'un fichier xib, c'est pour vous. J'ai créé la classe CustomCalloutView Sous-classe de UIView. J'ai créé un fichier xib et dans IB, sélectionnez simplement le propriétaire du fichier, puis sélectionnez Inspecteur d'attributs, définissez le nom de la classe sur CustomCalloutView, puis créez une sortie dans votre classe.
// L'ajout maintenant
la source
Voici un exemple de la façon dont je construis habituellement mes sous-classes (UIView). J'ai le contenu sous forme de variables afin qu'ils puissent être consultés et modifiés peut-être plus tard dans une autre classe. J'ai également montré comment j'utilise la mise en page automatique et l'ajout de contenu.
Par exemple, dans un ViewController, j'ai cette vue initialisée dans ViewDidLoad () car elle n'est appelée qu'une seule fois lorsque la vue est visible. Ensuite, j'utilise ces fonctions que je crée ici
addContentToView()
et làactivateConstraints()
pour créer le contenu et définir des contraintes. Si plus tard, dans un ViewController, je veux que la couleur, disons, d'un bouton soit rouge, je le fais simplement dans cette fonction spécifique de ce ViewController. Quelque chose comme:func tweaksome(){ self.customView.someButton.color = UIColor.red}
la source