通过使用协议点击滑出菜单来过滤 UITableView Feed
Filter UITableView Feed via tap on Slide Out Menu with protocol
假设您有一个滑出式菜单。当您从此滑出菜单中键入一个项目时,您希望使用位于该滑出菜单项中的 NSString 来过滤掉您的应用程序的提要,一个充满自定义单元格的 UITableView。
您认为正确的方法是使用协议和委托。
在滑出式菜单视图控制器中,声明协议、关联方法(在您的源视图控制器中实现)和委托。
// SlideOutMenuTableViewController.h
#import <UIKit/UIKit.h>
#import "SlideOutMenuItems.h"
#import "SlideOutMenuCellTableViewCell.h"
@protocol filterFeed <NSObject>
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData; //String to pass slideOut menu item string back to feed
@end
@interface SlideOutMenuTableViewController : UITableViewController
@property(nonatomic,assign)id<filterFeed> stringDelegate;
@end
在您的 Feed 视图控制器中,您有以下头文件和实现文件:
// FeedVCTableViewController.h
#import <UIKit/UIKit.h>
#import "FlameCellTableViewCell.h"
#import "Feed.h"
#import "SlideOutMenuTableViewController.h"
#import "FlameDetailViewController.h"
@interface FeedVCTableViewController : UITableViewController<FlameCellDelegate, senddataProtocol, filterFeed,UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate>
@property Feed *feed;
@property Feed *filteredFeed;
@property NSInteger *indexTapCell;
@end
// FeedVCTableViewController.m
#import "FeedVCTableViewController.h"
#import "Feed.h"
#import "SWRevealViewController.h"
#import <Parse/Parse.h>
@interface FeedVCTableViewController ()
@end
@implementation FeedVCTableViewController
// First quite a few methods not relevant to solve this
#pragma mark - Filter feed based on slideout menu item tapped
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData
{
NSLog(@"filterFeedFromSlideOutItemTapped just started");
if (!(slideOutItemStringData == (nil)))
{//Pass self.feed.flames + filtering string ==> filtered flames
NSMutableArray* allFlames = [[NSMutableArray alloc] initWithArray:self.feed.flames];
NSString *flameRelationFilter = slideOutItemStringData;
NSPredicate* sortFlames = [NSPredicate predicateWithFormat:@"(kFlameRelation like %@)", flameRelationFilter];
NSArray* filteredFlames = [allFlames filteredArrayUsingPredicate:sortFlames];
NSLog(@"The filter flames are %@", filteredFlames);
NSMutableArray *mutableFilteredFlames = [filteredFlames mutableCopy];
self.filteredFeed.flames = mutableFilteredFlames;
[self.tableView reloadData];
}
}
//Other methods not relevant here
@end
最后但同样重要的是,在验证您要传递给 stringDelegate 的 NSString 是 class NSString 并且正在传递预期值(位于点击出售内的 NSString):
#pragma mark - segue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:@"Filter_MenuItem"]) {
if ([sender isKindOfClass:[SlideOutMenuCellTableViewCell class]])
{
NSIndexPath* indexPath = [self.tableView indexPathForCell:sender];
NSLog(@"The indexPath of slideout cell is: %@", indexPath);
NSLog(@"class for object sender: %@", NSStringFromClass([sender class]));
//Assign tapped cell string to stringDelegate
NSLog(@"The NSString in the slide out menue item cell is %@",[self.slideOutMenuItems menuItemAtIndex:indexPath.row]);
if([[self.slideOutMenuItems menuItemAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSLog(@"The string of the tapped menu items is kind of class NSString");
}
NSLog(@"The stringDelegate value prior to executing the delegate method is %@",stringDelegate);
[stringDelegate filterFeedFromSlideOutItemTapped:[self.slideOutMenuItems menuItemAtIndex:indexPath.row]];
NSLog(@"The stringDelegate from the slide out menu VC has been set to %@", stringDelegate);
}
}
}
你也要确保在后一个实现中合成你的委托:
@implementation SlideOutMenuTableViewController
@synthesize stringDelegate;
您启动构建并崩溃并显示以下错误消息:
2015-10-13 15:15:06.245 Flame[1607:479051] The NSString in the slide out menue item cell is Friend into
2015-10-13 15:15:06.245 Flame[1607:479051] The string of the tapped menu items is kind of class NSString
2015-10-13 15:15:06.245 Flame[1607:479051] The stringDelegate value prior to executing the delegate method is All Flames
2015-10-13 15:15:13.270 Flame[1607:479051] -[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10
2015-10-13 15:15:13.272 Flame[1607:479051] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10'
*** First throw call stack:
(0x183e94f5c 0x19899bf80 0x183e9bc6c 0x183e98c14 0x183d9cdcc 0x1000e0d0c 0x189ad9c78 0x189ad9ae0 0x189ad9da8 0x18951dc6c 0x1895d8f8c 0x189694828 0x1896a0dc8 0x1893dd1c8 0x183e4bc30 0x183e499d4 0x183e49e04 0x183d78dc0 0x18eecc088 0x189452f44 0x1000e05ec 0x1991c68b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
如何解决?
非常感谢任何帮助。
谢谢!
你要注意的那一行是:
-[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10
这是在告诉您,您正在尝试通过字符串发送 filterFeedFromSlideOutItemTapped:
消息,这显然行不通。
您没有显示将此委托 属性 设置为符合 filterFeed
协议的实例的位置,因此这是您下一步需要查看的地方。
更新:
要正确设置它,实际上取决于您是使用故事板还是在代码中构建所有内容。如果您在代码中设置它,那么您需要找到创建这 2 个控制器(可能是导航控制器或拆分视图控制器)的公共父级并将委托设置在那里。
如果您使用故事板,则可以在设计器中连接委托。
如果这些选项中的任何一个都失败,您可以让您的 tableview 进入视图控制器层次结构并找到滑出控制器,以这种方式设置 属性,但这并不是很理想。
假设您有一个滑出式菜单。当您从此滑出菜单中键入一个项目时,您希望使用位于该滑出菜单项中的 NSString 来过滤掉您的应用程序的提要,一个充满自定义单元格的 UITableView。
您认为正确的方法是使用协议和委托。
在滑出式菜单视图控制器中,声明协议、关联方法(在您的源视图控制器中实现)和委托。
// SlideOutMenuTableViewController.h
#import <UIKit/UIKit.h>
#import "SlideOutMenuItems.h"
#import "SlideOutMenuCellTableViewCell.h"
@protocol filterFeed <NSObject>
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData; //String to pass slideOut menu item string back to feed
@end
@interface SlideOutMenuTableViewController : UITableViewController
@property(nonatomic,assign)id<filterFeed> stringDelegate;
@end
在您的 Feed 视图控制器中,您有以下头文件和实现文件:
// FeedVCTableViewController.h
#import <UIKit/UIKit.h>
#import "FlameCellTableViewCell.h"
#import "Feed.h"
#import "SlideOutMenuTableViewController.h"
#import "FlameDetailViewController.h"
@interface FeedVCTableViewController : UITableViewController<FlameCellDelegate, senddataProtocol, filterFeed,UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate>
@property Feed *feed;
@property Feed *filteredFeed;
@property NSInteger *indexTapCell;
@end
// FeedVCTableViewController.m
#import "FeedVCTableViewController.h"
#import "Feed.h"
#import "SWRevealViewController.h"
#import <Parse/Parse.h>
@interface FeedVCTableViewController ()
@end
@implementation FeedVCTableViewController
// First quite a few methods not relevant to solve this
#pragma mark - Filter feed based on slideout menu item tapped
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData
{
NSLog(@"filterFeedFromSlideOutItemTapped just started");
if (!(slideOutItemStringData == (nil)))
{//Pass self.feed.flames + filtering string ==> filtered flames
NSMutableArray* allFlames = [[NSMutableArray alloc] initWithArray:self.feed.flames];
NSString *flameRelationFilter = slideOutItemStringData;
NSPredicate* sortFlames = [NSPredicate predicateWithFormat:@"(kFlameRelation like %@)", flameRelationFilter];
NSArray* filteredFlames = [allFlames filteredArrayUsingPredicate:sortFlames];
NSLog(@"The filter flames are %@", filteredFlames);
NSMutableArray *mutableFilteredFlames = [filteredFlames mutableCopy];
self.filteredFeed.flames = mutableFilteredFlames;
[self.tableView reloadData];
}
}
//Other methods not relevant here
@end
最后但同样重要的是,在验证您要传递给 stringDelegate 的 NSString 是 class NSString 并且正在传递预期值(位于点击出售内的 NSString):
#pragma mark - segue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:@"Filter_MenuItem"]) {
if ([sender isKindOfClass:[SlideOutMenuCellTableViewCell class]])
{
NSIndexPath* indexPath = [self.tableView indexPathForCell:sender];
NSLog(@"The indexPath of slideout cell is: %@", indexPath);
NSLog(@"class for object sender: %@", NSStringFromClass([sender class]));
//Assign tapped cell string to stringDelegate
NSLog(@"The NSString in the slide out menue item cell is %@",[self.slideOutMenuItems menuItemAtIndex:indexPath.row]);
if([[self.slideOutMenuItems menuItemAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSLog(@"The string of the tapped menu items is kind of class NSString");
}
NSLog(@"The stringDelegate value prior to executing the delegate method is %@",stringDelegate);
[stringDelegate filterFeedFromSlideOutItemTapped:[self.slideOutMenuItems menuItemAtIndex:indexPath.row]];
NSLog(@"The stringDelegate from the slide out menu VC has been set to %@", stringDelegate);
}
}
}
你也要确保在后一个实现中合成你的委托:
@implementation SlideOutMenuTableViewController
@synthesize stringDelegate;
您启动构建并崩溃并显示以下错误消息:
2015-10-13 15:15:06.245 Flame[1607:479051] The NSString in the slide out menue item cell is Friend into
2015-10-13 15:15:06.245 Flame[1607:479051] The string of the tapped menu items is kind of class NSString
2015-10-13 15:15:06.245 Flame[1607:479051] The stringDelegate value prior to executing the delegate method is All Flames
2015-10-13 15:15:13.270 Flame[1607:479051] -[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10
2015-10-13 15:15:13.272 Flame[1607:479051] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10'
*** First throw call stack:
(0x183e94f5c 0x19899bf80 0x183e9bc6c 0x183e98c14 0x183d9cdcc 0x1000e0d0c 0x189ad9c78 0x189ad9ae0 0x189ad9da8 0x18951dc6c 0x1895d8f8c 0x189694828 0x1896a0dc8 0x1893dd1c8 0x183e4bc30 0x183e499d4 0x183e49e04 0x183d78dc0 0x18eecc088 0x189452f44 0x1000e05ec 0x1991c68b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
如何解决?
非常感谢任何帮助。
谢谢!
你要注意的那一行是:
-[__NSCFConstantString filterFeedFromSlideOutItemTapped:]: unrecognized selector sent to instance 0x100306d10
这是在告诉您,您正在尝试通过字符串发送 filterFeedFromSlideOutItemTapped:
消息,这显然行不通。
您没有显示将此委托 属性 设置为符合 filterFeed
协议的实例的位置,因此这是您下一步需要查看的地方。
更新:
要正确设置它,实际上取决于您是使用故事板还是在代码中构建所有内容。如果您在代码中设置它,那么您需要找到创建这 2 个控制器(可能是导航控制器或拆分视图控制器)的公共父级并将委托设置在那里。
如果您使用故事板,则可以在设计器中连接委托。
如果这些选项中的任何一个都失败,您可以让您的 tableview 进入视图控制器层次结构并找到滑出控制器,以这种方式设置 属性,但这并不是很理想。