Mis nooit een bericht

wenst u ooit dat Apple een extra initializer heeft toegevoegd aan een UIKit-klasse? Swift extensies maken het eenvoudig om nieuwe initializers toe te voegen aan typen zonder subclassering. Mijn snelle notities over het toevoegen van een nieuwe gemak initializer om een UIKit klasse met behulp van een Swift-extensie.

aangewezen of gemakshalve?

eerst een samenvatting van de twee typen initializer:

een aangewezen initializer is de primaire initializer voor een klasse. Het moet alle eigenschappen die door zijn klasse zijn geà ntroduceerd volledig initialiseren voordat het een superclass initializer aanroept. Een klasse kan meer dan één aangewezen initializer hebben.

een convenience initializer is een secundaire initializer die een aangewezen initializer van dezelfde klasse moet aanroepen. Het is handig wanneer u standaardwaarden of andere aangepaste instellingen wilt opgeven. Een klasse vereist geen gemak initializers.

de drie regels

met die clear moet u drie regels onthouden voor aangewezen en gemak initializers voor klasse types:

  • een aangewezen initializer moet een aangewezen initializer aanroepen vanuit de directe superklasse.
  • een convenience initializer moet een andere initializer uit dezelfde klasse aanroepen.
  • een convenience initializer moet uiteindelijk een aangewezen initializer aanroepen.

wat betekent dit voor ons? In eenvoudige termen, bel super niet vanuit uw gemak initializer. Bel een andere initializer (gemak of aangewezen) uit dezelfde klasse.

een praktisch voorbeeld

laten we het eens proberen met een praktisch voorbeeld. Het maken en configureren van een beeldweergave van een afbeelding in de asset catalogus klaar voor ons om te gebruiken met Auto lay-out vereist verschillende regels code:

// Create the imagelet heartImage = UIImage(named: "Heart")// Now create the image view using the imagelet heartImageView = UIImageView(image: heartImage)// Configure the view remembering to disable// the autoresizing mask if we are using// Auto LayoutheartImageView.translatesAutoresizingMaskIntoConstraints = false// Sometime we must also override the default content modeheartImageView.contentMode = .scaleAspectFit// Finally add to the view hierarchyview.addSubview(heartImageView)

dit wordt snel saai en ik vergeet altijd om de vertaling van het auto resizing masker uit te schakelen.

Maak een Convenience Initializer

laten we een nieuwe UIImageView convenience initializer maken die de configuratie voor ons uitvoert. Onze initializer neemt de naam van de afbeelding in de asset catalogus en de content mode. Omdat we niet altijd de inhoudsmodus willen instellen, maken we deze standaard op schaal om te vullen. Hier is de code:

extension UIImageView { convenience init?(named name: String, contentMode: UIViewContentMode = .scaleToFill) { guard let image = UIImage(named: name) else { return nil } self.init(image: image) self.contentMode = contentMode translatesAutoresizingMaskIntoConstraints = false }}

enkele punten om op te merken:

  • als de parameter image name ongeldig is, zal onze initializer falen en zou nilmoeten teruggeven. U definieert een failable initializer met een vraagteken na het init trefwoord (init?).
  • zodra we een geldige UIImage hebben, roepen we de aangewezen initializer van UIImageView aan om de afbeeldingsweergave aan te maken.
  • we kunnen alleen eigenschappen instellen op het UIImageView object nadat we de aangewezen initializer hebben aangeroepen.

voorbeeld gebruik

// Default contentModelet heart = UIImageView(named: "Heart")// Specifying a contentModelet star = UIImageView(named: "Star", contentMode: .scaleAspectFit)

merk op dat de failable initializer betekent dat het return type optioneel is (UIImageView?) dus we zouden het moeten uitpakken voordat we het aan de superview toevoegen.

Eigenschappentoegang voordat u zelf initialiseert

een laatste opmerking over wanneer u zelf kunt openen om eigenschappen te wijzigen. Als we proberen een eigenschap van UIImageView in te stellen voordat we self.init(image: UIImage?) hebben aangeroepen, krijgen we een fout:

// Does not compileself.contentMode = contentModeself.init(image: image)// Use of 'self' in property access 'contentMode'// before self.init initializes self

als je je herinnert dat een aangewezen initializer alle eigenschappen van zijn klasse volledig moet initialiseren, kun je misschien zien waarom dit niet is toegestaan. Zelfs als de compiler ons toestaat om dit te doen zou de aangewezen initializer onze waarde overschrijven met de standaard waarde.

verder lezen

de secties over initialisatie en uitbreidingen in de Swift Programming Language guide hebben veel meer details:

  • initialisatie
  • extensies

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.