2015-01-23 13 views
6

Ho sempre utilizzato il metodo loadNibNamed per il caricamento di viste personalizzate nei controller di visualizzazione, ma ora sto cercando di evitare di chiamare tale metodo all'esterno della visualizzazione personalizzata per renderlo più riutilizzabile in modo che se una persona usa il mio visualizzazione personalizzata che solo avrà bisogno di istanziare la vista senza loadFromNib, ad esempio:Uiview personalizzato con pennino in rapido senza utilizzare loadFromNib nel controller di visualizzazione

var myView: MyView = MyView() 

E l'aggiunta di questo punto di vista alla visualizzazione del controller della vista sarebbe sufficiente, la visualizzazione personalizzata verrà caricato il pennino dentro se stesso. Sto cercando di farlo in Swift, in objC ho trovato il codice come quello di questa risposta: UIView and initWithFrame and a NIB file. How can i get the NIB file loaded? Ma in rapida non posso usare l'init utilizzata la risposta:

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code. 
     // 
     [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil]; 
     [self addSubview:self.view]; 
    } 
    return self; 
} 

I avere questo metodo e si conclude con un ciclo infinito:

override init(frame: CGRect) { 
    super.init(frame: frame) 
    self.loadFromNibNamed("MyView") 
} 

ho anche provato ad aggiungere un altro vista all'interno MyView come IBOutlet come l'altra risposta dice e utilizzando tutte le INIT:

@IBOutlet var view: UIView! 

override init() { 
    super.init() 
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil) 
    self.addSubview(self.view) 
} 

override init(frame: CGRect) { 
    super.init(frame: frame) 
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil) 
    self.addSubview(self.view) 
} 

required init(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil) 
    self.addSubview(self.view) 
} 

Ma ho ancora l'errore del ciclo infinito.

Non riesco a trovare una buona soluzione e mi sta facendo impazzire !! Qualcuno può aiutarmi per favore? Grazie!

+0

La vostra NIB contengono una vista della classe 'MyView' o' MediaPlayerView', resp.? Questa potrebbe essere la ragione del ciclo infinito, e indovinerei "init (coder:)" come causa. – clemens

risposta

0

Penso che l'approccio più pulito sia non utilizzare gli inizializzatori predefiniti, ma utilizzare il proprio ad es. Ti piace questa

override init(frame: CGRect, shouldLoadFromNib: Bool) { 
    super.init(frame) 
    guard shouldLoadFromNib else { 
     return 
    } 
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil) 
    self.addSubview(self.view) 

} 

In questo modo, quando si è un'istanza che da qualche altra parte, si vedrà subito che questo non è solo il vecchio esemplificazione piana di alcuni UIView ma che ha effetti collaterali (che la vista sarà caricato da un pennino)

non sono sicuro circa la chiamata super.init(frame), è possibile che loadNibNamed sarà anche chiamare che per voi, così si potrebbe desiderare di controllare che fuori

0

stai diventando un ciclo infinito, perché loadNibNamed(_,owner:,options:) chiama un init, s o quindi provare a caricare di nuovo il pennino, e di nuovo uno così via ... Prova questo:

Swift 4

var contentView: UIView? 

// MARK: Initializers 

override init(frame: CGRect) { 
    super.init(frame: frame) 
    configureView() 
} 

required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    configureView() 
} 

override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 
    configureView() 
} 

override func awakeFromNib() { 
    super.awakeFromNib() 
    configureView() 
} 

// MARK: Config Functions 

func configureView() { 
    guard let view = defaultView() else { return } 
    view.frame = bounds 
    view.autoresizingMask = [.flexibleWidth, .flexibleHeight] 
    addSubview(view) 
    contentView = view 

    updateView() 
} 

func defaultView() -> UIView? { 
    // Create view from a nib with the same name 
    let nibName = String(describing: type(of: self)) 
    let bundle = Bundle(for: type(of: self)) 
    let nib = UINib(nibName: nibName, bundle: bundle) 

    return nib.instantiate(withOwner: self, options: nil).first as? UIView 
} 

cosa fa questo codice, è caricare la vista dal pennino, uno poi aggiungendolo ad una sottoview all'interno della tua vista.

Questo funziona anche quando si aggiunge la visualizzazione su un altro xibs, aggiungere @IBDesignable e diventerà disponibile

Problemi correlati