【问题标题】:Simple iOS Delegate Protocol Not Working With Passing Strings Between View Controllers简单的 iOS 委托协议不适用于在视图控制器之间传递字符串
【发布时间】:2014-04-23 18:52:00
【问题描述】:

我遇到了一个看似简单的问题,但我无法弄清楚它为什么不起作用。

我有一个标签栏,其中一个表视图(时间轴)用于主应用程序,一个用于设置。如果用户单击设置选项卡,他们就有机会选择一个主题,该主题只是另一个表格视图的形式,其中有许多代表主题的单元格。

如果用户点击主题“黑色”,我希望标签栏中的其他表格视图更改主题。

我不担心主题的实现;尽管我已经遵循了我认为在我的应用程序中使用其他委托协议所遵循的相同步骤,但我似乎在这里遇到了我的委托协议的问题。

这是我的主题表格视图:

// .h
@class SelectThemesTableViewController;

@protocol SelectThemesTableViewControllerDelegate <NSObject>
- (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme;
@end

@interface SelectThemesTableViewController : UITableViewController

@property (nonatomic, weak) id <SelectThemesTableViewControllerDelegate> delegate; 
@property (nonatomic, strong) NSString *selectedTheme; 
// .m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
    self.selectedTheme = selectedCell.textLabel.text;
    [self.delegate selectThemesTableViewController:self didSelectCell:self.selectedTheme];
    NSLog(@"The value of the selected cell is %@", self.selectedTheme); 
}

在我希望传递字符串的主表视图中:

// .h
@property (nonatomic, strong) NSString *selectedTheme;

// .m
@interface TimelineTableViewController () <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, NSFetchedResultsControllerDelegate, SelectThemesTableViewControllerDelegate>

@end

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    SelectThemesTableViewController *selectThemesTableViewController = [[SelectThemesTableViewController alloc] init];
    selectThemesTableViewController.delegate = self;

    NSLog(@"What is this value %@", self.selectedTheme);
    if ([self.selectedTheme isEqualToString:@"Black"])
    {   
        NSLog(@"The value is %@", self.selectedTheme); 

    }
    else
    {
        NSLog(@"Nope");
    }
}

// Here in the viewWillAppear, I'm clearly setting the delegate but the self.selectedTheme is always nil. 

// Delegate method in the Timeline Table view:

- (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme
{
    self.selectedTheme = selectedTheme;
    NSLog(@"String = %@", self.selectedTheme);
    // The selectedTheme is always nil here 
}

我已经放置了断点并跟踪了跟踪,但是在 themeTableView 中,NSLog 显示我选择了“黑色”单元格,当委托发生在时间轴上时,它总是为零。

我正在使用带有自定义静态单元格的分组表视图(据我所知,ThemesTableView 上不需要 cellForRowAtIndexPath,是吗?

更新:SelectThemesTableViewController

在情节提要中,SelectThemesTableViewController 是从 Settings Table View Controller 选项卡形成的 segue(推送)。所以我在标签栏中有两个标签;第一个是时间轴,第二个是 SettingsTableViewController。这是嵌入在导航控制器中的。 Table 视图中的第一个单元格称为“Themes”,单击该单元格后,SelectThemesTableViewController 会出现一个 segue(推送)。我没有在任何地方准备ForSegue,但这让我想到也许我应该这样做?

我错过了什么?任何帮助将不胜感激!

【问题讨论】:

    标签: ios iphone uitableview protocols delegation


    【解决方案1】:

    由于您在标签栏中同时使用两个控制器,因此没有任何选项可以将委托设置为彼此。相反,您可以做的只是在 didSelectRow 委托方法内的 SelectThemesTableViewController 中使用所选主题名称更新 NSUserDefaults,当用户再次点击第一个选项卡时,只需检查 TimelineTableViewController 的 viewWillAppear 方法中的 NSUserDefault 值并根据该值更新 UI。

      // .h
    
        @interface SelectThemesTableViewController : UITableViewController
    
        @property (nonatomic, strong) NSString *selectedTheme;
    
        @end
    
        // .m
        - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
        {
            UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
            self.selectedTheme = selectedCell.textLabel.text;
            [[NSUserDefaults standardUserDefaults] setObject:self.selectedTheme forKey:@"Theme"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            NSLog(@"The value of the selected cell is %@", self.selectedTheme); 
        }
    
        ------------------------------------------------------------------------------------
    
        // .h
        @property (nonatomic, strong) NSString *selectedTheme;
    
        // .m
        @interface TimelineTableViewController () <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, NSFetchedResultsControllerDelegate>
    
        @end
    
        - (void)viewWillAppear:(BOOL)animated
        {
            [super viewWillAppear:animated];
            self.selectedTheme = [[NSUserDefaults standardUserDefaults] objectForKey:@"Theme"];
            NSLog(@"What is this value %@", self.selectedTheme);
            if ([self.selectedTheme isEqualToString:@"Black"])
            {   
                NSLog(@"The value is %@", self.selectedTheme); 
    
            }
            else
            {
                NSLog(@"Nope");
            }
        }
    

    【讨论】:

    • 绝对做到了!非常感谢山姆——如果我能多次投票,我会的。使用这种技术,我能够确保应用程序在整个生命周期中的一致性,以及当它关闭并从多任务处理中终止时。非常感谢你做的这些。真的很有帮助!
    【解决方案2】:

    故事板更新

    好的,您没有提到您正在使用情节提要。您不应该在任何地方创建视图控制器

    您的 Prepare 需要看起来像这样...

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        //The string needs to be whatever you've set up as the identifier in storyboard
    
        if ([segue.identifier isEqualToString:@"themes"]) {
            SelectThemesTableViewController * themeSelector = (SelectThemesTableViewController *) segue.destinationViewController;
            themeSelector.delegate = self;
        }
    }
    

    【讨论】:

    • 非常感谢@Flexicoder,这实际上很有意义。我进行了更改,但奇怪的是 self.selectedTheme 仍然为零。我将尝试使用它,但我不确定我错过了什么 - 尽管您的建议确实完全有道理.. 有什么想法吗?
    • 认为两行赋值应该在viewDidLoad,而不是viewWillAppear。每次返回视图时都会覆盖这些值
    • 感谢@Flexicoder - 试过了,但似乎没有用。但是我确实注意到了委托方法 - (void)selectThemesTableViewController:(SelectThemesTableViewController *)controller didSelectCell:(NSString *)selectedTheme 在时间轴中不会被调用,因为那里的 NSLog ( NSLog(@"String = %@" , self.selectedTheme); 永远不会被触发。如果我​​从 viewDidLoad 或 viewDIdAppear 调用这个方法,它仍然是 nil,但我一直认为你不必专门调用这个.. 无论如何它应该触发?
    • 您能否更新您的问题,说明您如何展示SelectThemesTableViewController - 您是否在展示之前创建另一个问题?你应该使用你现在在viewDidLoad中创建的那个
    • 谢谢 - 我刚刚更新了最后的问题。你让我思考;我没有在任何地方做prepareForSegue,我不确定在哪里使用现在在viewDidLoad 中使用的新self.selectThemesTableViewController。也许没有参考。我的意思是segue有一个标识符,但我不是从任何地方调用它。也许我需要从 SettingsTableView 调用它?
    【解决方案3】:

    委托协议没有错误。您的委托设置有问题。您正在创建单独的视图控制器并将其委托分配为 self。按下设置选项卡按钮时,显示的不是视图控制器。要解决此委托设置方法并在 SelectThemesTableViewController 中添加以下代码。它应该可以工作。

    // assume that first view controller in Tabbar view controller is TimelineTableViewController
    //Or else specify correct index of view controller when assigning to delegate.
    -(void)viewDidAppear:(BOOL)animated
    {
       [super viewDidAppear:animated];
       self.delegate = self.tabBarController.viewControllers[0];
    }
    

    【讨论】:

    • 谢谢@rajath - 在我的 SelectThemesTableViewController 中使用该代码,由于未捕获的异常 'NSInvalidArgumentException',我正在终止应用程序崩溃,原因:'-[UINavigationController selectThemesTableViewController:didSelectCell:]:无法识别的选择器发送到实例 我的代码有问题吗?
    • 亲爱的@rajath - 非常感谢您抽出宝贵的时间来回答问题,下面来自 sam 的回答成功了。不过,我感谢您对此的想法和努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多