128 votos

¿Llegar a UIViewController desde UIView en iPhone?

¿Hay una manera incorporada para obtener de una UIView a su UIViewController ? ¿Sé que se puede obtener de UIViewController a su UIView vía [self view] pero me preguntaba si hay una referencia inversa?

167voto

Phil M Puntos 1368

Utilizando el ejemplo publicado por Brock, la he modificado para que su categoría de UIView lugar UIViewController y lo hizo recursiva, de manera que cualquier subvista puede (con suerte) encontrar la matriz UIViewController.

@interface UIView (FindUIViewController)
- (UIViewController *) firstAvailableUIViewController;
- (id) traverseResponderChainForUIViewController;
@end

@implementation UIView (FindUIViewController)
- (UIViewController *) firstAvailableUIViewController {
    // convenience function for casting and to "mask" the recursive function
    return (UIViewController *)[self traverseResponderChainForUIViewController];
}

- (id) traverseResponderChainForUIViewController {
    id nextResponder = [self nextResponder];
    if ([nextResponder isKindOfClass:[UIViewController class]]) {
        return nextResponder;
    } else if ([nextResponder isKindOfClass:[UIView class]]) {
        return [nextResponder traverseResponderChainForUIViewController];
    } else {
        return nil;
    }
}
@end

Para utilizar este código, agregue en un nuevo archivo de clase (I nombre de la mina "UIKitCategories") y eliminar los datos de la clase... de la copia de la @interfaz en la cabecera, y el @implementación en el .m archivo. A continuación, en su proyecto, #import "UIKitCategories.h" y su uso dentro de la UIView código:

// from a UIView subclass... returns nil if UIViewController not available
UIViewController * myController = [self firstAvailableUIViewController];

102voto

Brock Puntos 871

UIView es una subclase de UIResponder. UIResponder establece el método -nextResponder con una aplicación que devuelve nil. UIView anula este método, como se documenta en UIResponder (por alguna razón, en lugar de en UIView) como sigue: si la vista tiene un controlador de vista, es devuelto por -nextResponder. Si no hay ningún controlador de vista, el método devolverá el superview.

Agregue esto a su proyecto y usted está listo para rodar.

@interface UIView (APIFix)
- (UIViewController *)viewController;
@end

@implementation UIView (APIFix)

- (UIViewController *)viewController {
    if ([self.nextResponder isKindOfClass:UIViewController.class])
        return (UIViewController *)self.nextResponder;
    else
        return nil;
}
@end

Ahora, UIView tiene un método de trabajo para regresar a la vista del controlador.

24voto

de. Puntos 442

Yo sugeriría un enfoque más ligero para recorrer la cadena de respuesta completa sin tener que agregar una categoría en UIView:

@implementation MyUIViewSubclass

- (UIViewController *)viewController {
    UIResponder *responder = self;
    while (![responder isKindOfClass:[UIViewController class]]) {
        responder = [responder nextResponder];
        if (nil == responder) {
            break;
        }
    }
    return (UIViewController *)responder;
}

@end

20voto

Randy Marsh Puntos 3229

La combinación de varios ya han dado respuestas, estoy de envío así con mi aplicación:

@implementation UIView (AppNameAdditions)

- (UIViewController *)appName_viewController {
    /// Finds the view's view controller.

    // Take the view controller class object here and avoid sending the same message iteratively unnecessarily.
    Class vcc = [UIViewController class];

    // Traverse responder chain. Return first found view controller, which will be the view's view controller.
    UIResponder *responder = self;
    while ((responder = [responder nextResponder]))
        if ([responder isKindOfClass: vcc])
            return (UIViewController *)responder;

    // If the view controller isn't found, return nil.
    return nil;
}

@end

La categoría es parte de mi ARCO-habilitada la biblioteca estática que yo buque en todas las aplicaciones que yo he creado. Se ha probado varias veces y no he encontrado ningún tipo de problemas o fugas.

P. S.: no es necesario el uso de una categoría como lo hice yo si la cuestión de la vista es una subclase de la suya. En el último caso, sólo tienes que poner el método en la subclase y ya está bueno para ir.

12voto

Ushox Puntos 598

Aunque esto puede resolverse técnicamente como recomienda pgb , IMHO, esto es un fallo de diseño. El punto de vista no debería ser consciente de la controladora.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: