ios - IBOutlet no está conectado en awakeFromNib
uiscrollview (4)
El código de muestra vinculado aquí funciona muy bien y permite que UIScrollView muestre imágenes con paginación y vista previa de las imágenes antes y después de la imagen actual:
- http://blog.proculo.de/archives/180-Paging-enabled-UIScrollView-With-Previews.html
- https://github.com/alexrepty/Paging-Enabled-UIScrollView-With-Previews
Estoy intentando encapsular el ejemplo en un solo control que se puede reutilizar. Así que creé un PagingScrollView:
@interface PagingScrollView : UIView {
IBOutlet UIScrollView * scrollView;
}
@property (nonatomic,retain) IBOutlet UIScrollView * scrollView;
@end
con la implementación de la suciedad simple
- (void) awakeFromNib
{
[super awakeFromNib];
NSLog(@"awake from nib");
}
En PagingScrollView.xib, puse una vista que contenía un UIScrollView y un ARScrollViewEnhancer exactamente como en el ScrollViewPagingExampleViewController xib original. La clase del propietario de su archivo está establecida en PagingScrollView, y su salida scrollView está configurada en el UIScrollView secundario.
En ScrollViewPagingExampleViewController, simplemente declaro:
IBOutlet PagingScrollView *pagingScrollView;
Y en IB, arrastro una Vista, configuro su clase a PagingScrollView y engancho su salida pagingScrollView a PagingScrollView.
En awakeFromNib, la propiedad scrollView es nil. Pensaría que dado que el scrollView está conectado en IB en la misma punta, estaría disponible para este punto.
Confusamente, en ScrollViewPagingExampleViewController.xib, hay una salida vacía llamada scrollView. Esto podría indicar que hay una instancia diferente de PagingScrollView que la definida en PagingScrollView.xib.
Como resultado, no puedo llenar el UIScrollView con las vistas secundarias reales. ¿Qué estoy haciendo mal aquí?
Aquí hay una muy buena respuesta a esta pregunta: ¿ Acceder a la vista en awakeFromNib?
En pocas palabras, la vista puede cargarse en awakeFromNib, pero su contenido está cargado de manera perezosa, por lo que debe usar viewDidLoad en lugar de awakeFromNib para lo que está tratando de lograr.
Estaba teniendo este problema y como usted, los otros artículos no se aplicaron. Tenía un ViewController, que tenía su propia vista. En el archivo .xib de ViewController, puse una vista y le asigné la clase de CustomView. Esto funcionaría muy bien, excepto por el hecho de que CustomView se definió en su propio archivo .xib, por lo que, naturalmente, en awakeFromNib todos los IBOutlets eran nulos. Esto se debe a que no hay forma en el generador de interfaces de vincular archivos .xib entre sí. Entonces, cuando la vista de mi ViewController se pone en la pantalla, intenta crear una instancia de CustomView, en lugar de cargar el archivo CustomView.xib.
Hay un trabajo detallado aquí http://cocoanuts.mobi/2014/03/26/reusable/ , pero lo esencial es que tuve que implementar lo siguiente en mi clase CustomView
@implementation CustomView
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (![self.subviews count])
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSArray *loadedViews = [mainBundle loadNibNamed:@"CustomView" owner:nil options:nil];
return [loadedViews firstObject];
}
return self;
}
@end
Para cualquiera que encuentre esto buscando la respuesta adecuada en Swift 4, aquí tienes.
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}
Sin embargo, descubrí que el verdadero secreto es que no subclasificas la vista principal de un archivo .xib. En su lugar, haga que el propietario del archivo sea la clase que desea que sea y agregue el Nib como así dentro de las clases init:
let bundle: Bundle = Bundle(for: type(of: self))
let nib: UINib = UINib(nibName: "<Nib File Name>", bundle: bundle)
if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.translatesAutoresizingMaskIntoConstraints = true
addSubview(view)
}
Utilizando Swift, puede usar el elemento dentro de su vista personalizada una vez que se establece:
class PointsTableViewCell: UITableViewCell {
@IBOutlet weak var pointsTitleLabel: UILabel! {
didSet {
self.pointsTitleLabel.text = "Points"
}
}
}