隐藏以编程方式创建的自动完成 UITableView

Posted

技术标签:

【中文标题】隐藏以编程方式创建的自动完成 UITableView【英文标题】:Hiding an autocomplete UITableView that was created programmatically 【发布时间】:2014-01-14 19:04:20 【问题描述】:

我正在使用 tutorial 的自动完成 UITableView 构建一个应用程序。我的自动完成功能正常工作,但我希望 UITableView-autocomplete 下拉菜单在单击该单词或在外部触摸它时消失。当以编程方式设置对象时,我不确定如何设置委托。我只使用界面生成器完成了这项工作。

.h

@interface slrpViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>

NSMutableArray *dataArray;
NSMutableData *receivedData;

NSMutableArray *pastUrls;
NSMutableArray *autocompleteUrls;
UITableView *autocompleteTableView;

@property(nonatomic, retain) IBOutlet UITextField *eWordEntered;
@property (nonatomic, retain) NSMutableArray *pastUrls;
@property (nonatomic, retain) NSMutableArray *autocompleteUrls;
@property (retain, nonatomic) NSMutableData *responseData;
@property (nonatomic, retain) UITableView *autocompleteTableView;
-(void)setReceivedData:(NSMutableData*)pReceivedData;
-(NSMutableData *) getReceivedData;
-(void) getAutoCompleteArray;
-(void)searchAutocompleteEntriesWithSubstring:(NSString *)substring;

.m

- (void)viewDidLoad

[super viewDidLoad];
[self getAutoCompleteArray];
pastUrls = [[NSMutableArray alloc] init];

NSLog(@"In the viewDidLoad and pasturl is: %@", self.pastUrls);
self.autocompleteUrls = [[NSMutableArray alloc] init];

autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(210, 225, 310, 120) style:UITableViewStylePlain];
self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
[self.view addSubview:autocompleteTableView];

-(void)setReceivedData:(NSMutableData*)pReceivedData

receivedData = pReceivedData;


-(NSMutableData *) getReceivedData
return receivedData;


-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

[receivedData setLength:0];   


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
[receivedData appendData:data];


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

NSError *e = nil;
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: receivedData options:  NSJSONReadingMutableContainers error: &e];

NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:receivedData
                                                         options:kNilOptions
                                                           error:&error];
seneca_word.ids = [jsonDict objectForKey:@"ids"];
NSArray *array_ids = [jsonDict objectForKey:@"ids"];
NSString *ids = array_ids[0];
seneca_word.ids = ids;
for (id key in jsonDict)

    NSLog(@"key: %@, value: %@", key, [jsonDict objectForKey:key]);
    NSLog(@"The value of bases by itself is: %@", [jsonDict objectForKey:@"bases"]);


if (!jsonArray)

    NSLog(@"Error parsing JSON: %@", e);

else

    if([jsonDict objectForKey:@"english"] != nil)
        pastUrls = [jsonDict objectForKey:@"bases"];
    

    else
        //Some of JSON object that I don't want to use here

//else   
//(void)connectionDidFinishLoading

- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring 
[autocompleteUrls removeAllObjects];
for(NSString *curString in pastUrls) 
    NSRange substringRange = [curString rangeOfString:substring];
    if (substringRange.location == 0) 
        [autocompleteUrls addObject:curString];
    

[autocompleteTableView reloadData];



- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
autocompleteTableView.hidden = NO;

NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section 
return autocompleteUrls.count;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = @"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];


cell.textLabel.text = [autocompleteUrls objectAtIndex:indexPath.row];
return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
self.eWordEntered.text = selectedCell.textLabel.text;

if(tableView == autocompleteTableView)
    //The autocomplete table view is the one that fired the didSelect delegate method
    //So hide the autocomplete table.
    //do whatever else you need to do to empty the autocompleteTableView's data source
    //or/and simply hide the table after that
    [autocompleteTableView setHidden:YES];    



-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

//When the user clicks outside of the uitableview it will disappear
[autocompleteTableView setHidden:YES];

如您所见,我使用从 RESTful API 获得的 JSON 数据填充了自动完成 UITableView。

我收到了警告,Assigning to 'id&lt;UITableViewDelegate&gt;' from incompatible type 'ViewController *const __strong' 的行:

self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;

我想,一旦我把代表的东西整理好,我就可以做我想做的事了。我做了一些研究并尝试创建一个委托类,但无法使该解决方案发挥作用。我什至不确定这是否是解决此问题的正确方法,因为我通常通过界面构建​​器而不是以编程方式来做这些事情。非常感谢任何方向或帮助。谢谢!

【问题讨论】:

【参考方案1】:

您应该使用 tableView 的 didSelectCellAtIndexPathRow 委托方法来识别用户对来自 tableView 的单元格的点击。如果您以编程方式创建 tableView 就可以了。

    只需确保 UIViewController 符合 UITableViewDelegate 和 UITableViewDataSource 协议即可。

    确保将 tableView 的 delegate 和 dataSource 属性设置为 self。

    在 viewController 的 .m 文件中实现 didSelectCellAtIndexPathRow 委托方法,如下所示:

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    
    
    

    然后在该委托方法中,您需要帮助检测您的 didSelect 方法是从哪个 tableView 触发的,因为您只想在用户从该表中选择一个单元格时隐藏自动完成表。因此,您可以像这样进行简单的 tableView 检查:

    if(tableView == autocompleteTableView)
        //The autocomplete table view is the one that fired the didSelect delegate method
        //So hide the autocomplete table.
        //do whatever else you need to do to empty the autocompleteTableView's data source
        //or/and simply hide the table after that 
        [autocompleteTableView setHidden:YES];
    
    

    您可能还想确保在用户在文本字段中输入内容时将 autocompleteTableView 隐藏属性设置为 NO,以便自动完成可以再次显示。

这就是朋友。

【讨论】:

谢谢!我更新了代码/问题以反映 3、4、5。当用户单击其中一个选项时,uitableview-autocomplete 现在确实会成功消失。我喜欢它现在在用户输入时“刷新”的方式。如果用户在 uitableview 之外单击,有没有办法让 uitableview 消失?就像 uitableview 和 viewcontroller 之外的任何地方一样?不确定这是否应该是单独的问题,但我想我会问。 您也可以在 touchesBegan 中执行相同的操作。我建议您对 touchesBegan 方法进行一些研究,该方法将检测屏幕上任何位置的触摸,如果尚未隐藏,您可以再次将 autoCompleteTableView 的 hidden 属性设置为 YES。【参考方案2】:

尝试设置 self.autocompleteTableView.hidden = YES;

【讨论】:

以上是关于隐藏以编程方式创建的自动完成 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

El capitan 中以编程方式“自动隐藏菜单栏”

无法隐藏以编程方式创建的 UIButton

以编程方式创建的 UITextField 隐藏了其他控件

iOS 以编程方式生成的视图具有隐藏的约束,导致与自动布局发生冲突

隐藏以编程方式为标签创建的 UIButton

在编辑表单上以编程方式选择自动完成设置值 ngModel