【问题标题】:How do you access a uitableview inside a uinavigationcontroller inside a uitabbarcontroller from app delegate?如何从应用程序委托访问 uitabbarcontroller 内的 uinavigationcontroller 内的 uitableview?
【发布时间】:2013-04-02 14:59:55
【问题描述】:

我试图从作为我的根的 tabbarcontroller 访问位于导航控制器内的 uitableview 中的刷新控制方法,但我无法获得准确的句柄。

到目前为止,这是我在 AppDelegate 中的代码,但它不起作用...

UITableViewController *tableView = (UITableViewController *)[[self.tabbarController viewControllers][0] tableView];
    [tableView.refreshControl beginRefreshing];

我有 5 个标签栏项目,我相信我可以通过 [0]、[1]、[2]、[3] 访问它们 而我在 UITableView 中的代码(虽然可能无关紧要)...

// Add Refresh Control
    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    [refreshControl addTarget:appDelegate action:@selector(forceDownload) forControlEvents:UIControlEventValueChanged];
    self.refreshControl = refreshControl;
    [refreshControl release];

任何帮助将不胜感激,因为我无法找到任何可以访问如此深入的在线网站。

【问题讨论】:

  • 这听起来像是个可怕的主意。你到底想达到什么目的?
  • 我获取一个 gps 位置,然后下载一个 json 文件以从应用程序委托填充一个 uitableview。我只是想确保当应用程序下载数据时活动指示器在顶部显示动画时,refreshControl 是匹配的。

标签: objective-c uinavigationcontroller uitabbarcontroller uitableview appdelegate


【解决方案1】:

如果您需要在不相关的对象之间进行通信,我认为最好的选择是使用 NSNotifications。这允许您使用单例对象[NSNotificationCenter defaultCenter],将通知从一个对象传递到另一个(或许多其他对象)。

所以你可以把 AppDelegate 对象(或其他对象)放在观察一个特定的通知,然后当你需要刷新控件时用 tableviewController 发布通知。

在应用委托类中,您可以像这样添加观察者:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(forceDownload)
                                             name:@"ForceDownloadNotification"
                                           object:nil];

并且,在 tableviewController 中,您可以发布 de 通知,例如:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ForceDownloadNotification" 
                                                    object:self];

在这里,我使用名称“ForceDownloadNotification”作为通知的名称。您可以使用所需的名称,但为了使此解决方案正常工作,您必须在开始观察和发布通知时使用相同的名称。

Here你有关于这个主题的教程。

【讨论】:

    【解决方案2】:

    我喜欢 Luis Espinoza 的方法,但这并不能回答问题本身

    如果您想调用嵌套在 UINavigationController 中的 UITableViewController 中的方法,该 UINavigationController 是 App Delegate 的 rootViewController。首先,我们使用 UITableViewController(或子类)创建一个 navigationController:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // Override point for customization after application launch.
    CustomTableViewController *nuTableVC = [[CustomTableViewController alloc] initWithStyle:UITableViewStylePlain];
    UINavigationController *nuNavController = [[UINavigationController alloc] initWithRootViewController:nuTableVC];
    self.window.rootViewController = nuNavController;
    
    [self.window makeKeyAndVisible];
    return YES;
    }
    

    然后在您的 UITableViewController(或子类)中设置刷新控件,就像您问的那样:

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Add Refresh Control
        UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
        [refreshControl addTarget:[[UIApplication sharedApplication] delegate]
                           action:@selector(forceDownload) 
                 forControlEvents:UIControlEventValueChanged];
        self.refreshControl = refreshControl;
    }
    

    最后要访问 UItableViewController 你必须检查实例是否真的是你想要的类,这是我在 App Delegate 中创建的方法 (forceDownload) 的实现强>:

    - (void)forceDownload {
    NSLog(@"force download method in App Delegate");
    UINavigationController *someNavController = (UINavigationController*)[_window rootViewController];
    
    UIViewController *vcInNavController = [[someNavController viewControllers] objectAtIndex:0];
    
    if ([vcInNavController isKindOfClass:[CustomTableViewController class]]) {
        NSLog(@"it is my custom Table VC");
        NSLog(@"here we can stop the refresh control, or whatever we want");
        CustomTableViewController *customTableVC = (CustomTableViewController *)vcInNavController;
        [customTableVC.refreshControl performSelector:@selector(endRefreshing)
                                           withObject:nil
                                           afterDelay:1.0f];
        }
    }
    

    我个人更喜欢使用 NSNotificationCenter,因为它更简单,但这并不意味着我们无法按照您最初计划的方式访问对象。

    (如果您想要示例代码,请索取)。

    问候。

    【讨论】:

      【解决方案3】:

      如果您的目标确实是让您的刷新控制与 networkActivityIndi​​cator 同步,那么一个选项是 KVO。

      在 viewController 的 viewDidAppear: 中添加类似这样的内容

      - (void)viewDidAppear:(BOOL)animated
      {
        [super viewDidAppear:animated];
      
        UIApplication *application = [UIApplication sharedApplication];
        [application addObserver:self
                      forKeyPath:@"networkActivityIndicatorVisible"
                         options:NSKeyValueObservingOptionNew
                         context:myContext];
      
        self.refreshControl.refreshing = [application isNetworkActivityIndicatorVisible];
      }
      

      然后确保在 viewController 不需要它时移除这个观察者——也许在viewDidDisappear:

      - (void)viewWillDisappear:(BOOL)animated
      {
        [super viewDidDisappear:animated];
        [[UIApplication sharedApplication] removeObserver:self
                                               forKeyPath:@"networkActivityIndicatorVisible"
                                                  context:myContext];
      }
      

      现在开始实际工作

      - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
      {
        if (myContext == context) {
          self.refreshControl.refreshing = [change[NSKeyValueChangeNewKey] boolValue];
        } else {
          [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-11-24
        • 2015-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-30
        • 2010-10-16
        • 2011-03-05
        • 1970-01-01
        相关资源
        最近更新 更多