Tableview search, cuts display - objective-c

Hey guys I simply can't solve this problem i've got.
http://i.imgur.com/LjliN7y.png
I have tried setting bounds of the UITableView like so:
[tableView setBounds:CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, 320, self.view.size.height)];
That didn't seem to fix my problem(See picture above), I thought maybe it was some clipping under the settings of the search bar which it wasn't.
I also tried setting the size of the UITableView that didn't help me.
It's also weird when using the UITableView without searching it works fine and the cells go full size.
But as soon as i search it starts clipping like that.
I've tried searching on the internet for a solution, i don't seem to find anything.
here is the rest of my search code:
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
UIButton *cancelButton;
UIView *topView = controller.searchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSString *predicateString = [NSString stringWithFormat:#"SELF beginsWith[cd] '%#'", searchText];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:predicateString];
searchResults = [combine filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}

Check size of the table view for the UISearchDisplayController:
NSLog(#"%#",[self.searchDisplayController.searchResultsTableView description]);

Related

how can I make clickable url in NSTableView

I am trying to build OS-X core data based app. In one of the entities, I am storing an URL ex. (www.somesite.com/somepage/someindex.php)
Using binding, I am successfully displaying the URL in the NSTableView. I would like however that URL to be clickable, and when clicked, browser to fire up and open the page. I have done some research, and I have found some solutions, for example:
Clickable url link in NSTextFieldCell inside NSTableView?
also:
https://developer.apple.com/library/mac/qa/qa1487/_index.html
but they both look outdated, first one is six years old, while the second is last updated on Jan. 2005
Anyone can provide easier & faster way how to achieve this? I didn't expected that I will have to write bunch of code just to make simple link to work to be honest... I am coming from web development world, where those kind of things can be sorted out withing few seconds, while here seems to be totally different story....
Any help will be appreciated.
John
You can use NSTextView and implement its delegate. There is a demo:
// MyCellView.h
#interface MyCellView : NSView
#property (nonatomic, strong) IBOutlet NSTextView *textView;
#end
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
NSNib *nib = [[NSNib alloc] initWithNibNamed:#"MyCellView" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:nib forIdentifier:#"MyCell"];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
MyCellView *cell = (MyCellView *)[tableView makeViewWithIdentifier:#"MyCell" owner:self];
cell.textView.delegate = self;
[cell.textView.textStorage setAttributedString:[self makeLinkAttributedString:#"This is a test: www.somesite.com/somepage/someindex.php"]];
return cell;
}
- (NSAttributedString *)makeLinkAttributedString:(NSString *)string {
NSMutableAttributedString *linkedString = [[NSMutableAttributedString alloc] initWithString:string];
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
[detector enumerateMatchesInString:string options:0 range:NSMakeRange(0, string.length) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
if (match.URL) {
NSDictionary *attributes = #{ NSLinkAttributeName: match.URL };
[linkedString addAttributes:attributes range:match.range];
}
}];
return [linkedString copy];
}
#pragma mark - NSTextViewDelegate methods
- (BOOL)textView:(NSTextView *)textView clickedOnLink:(id)link atIndex:(NSUInteger)charIndex {
// The click will be handled by you or the next responder.
return NO;
}
You can use TTTAttributedLabel in your tableviewcell. It supports powerful link detection.

UISearchDisplayController result table position issue in iOS7

Trying to implement UISearchBar into UINavigationBar my result tableview position become wrong (pic 2):
I've spent a couple of days to solve this issue, but there is no success )
Thanks!
EDITED
In my viewDidLoad:
[self.searchDisplayController.searchBar setPlaceholder:NSLocalizedString(#"SEARCH_PLACEHOLDER", nil)];
[self.searchDisplayController setDisplaysSearchBarInNavigationBar:YES];
My SearchDisplayController Delegate methods:
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
//filter work repfectly
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"not (isFav == 100)"];
[_fetchedResultsController.fetchRequest setPredicate:resultPredicate];
[self performFetch];
}

UISearchDisplayController search bar types letters automatically

On editing the Search Bar in UISearchDisplayController, it repeats the first typed letter recursively until the second letter pressed.
Here is what happens:
Please suggest any possible solution.
Code:
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContent:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)SearchBar
{
[SearchBar resignFirstResponder];
SearchBar.text = #"";
[self.tableView reloadData];
}
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
controller.searchBar.showsCancelButton = YES;
}
-(void)filterContent:(NSString*)searchText scope:(NSString*)scope
{
_searchArray = [[NSArray alloc] init];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:[NSPredicate predicateWithFormat:#"SELF.user_name contains[c] %#", searchText], [NSPredicate predicateWithFormat:#"SELF.country_name contains[c] %#", searchText], [NSPredicate predicateWithFormat:#"SELF.city contains[c] %#", searchText], nil]];
_searchArray = [_users filteredArrayUsingPredicate:predicate];
}
#JananiM I think you having problem in this line [self filterContent:searchString...] which u assigned in your delegate method.
Try this one
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString
scope:[self.searchDisplayController.searchBar scopeButtonTitles][[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
i have implemented your code (which you posted above) in my application.I didn't get anything like this.I have checked breakpoint too.Check this

Get labels in current view

I have a need to get all labels in current view. is it possible? If yes, please advise how can i realize this?
For example, i need to collect all labels from startup screen, then from currently showing popup and etc.
Thanks!
Here is the way to go----
NSMutableArray *labels = [NSMutableArray array];
for (UIView *v in someSuperview.subviews) {
if ([v isKindOfClass:[UILabel class]]) {
[labels addObject:v];
}
}
Suppose if you want to collect label in an array, you can try this:
for (UIView *subview in self.view.subviews)
{
if(subview isKindOfClass:[UILabel class])
{
[arrayOfLabels addObject:subview];
}
}
If you want it to do by means of accessibilityLabel, here are the steps to get view from given accessibilityLabel. Method viewContainingAccessibilityElement:element is extension method to UIAccessibilityElement class.
UIAccessibilityElement *element = [[UIApplication sharedApplication] accessibilityElementWithLabel:label];
UIView *view = (UIView*)[UIAccessibilityElement viewContainingAccessibilityElement:element];
Let me know if it works

Data doesn't load in UITableView until I scroll

I am trying to load parsed data in cells, but the problem is that it is happening synchronously and UitableView doesn't show until the data has finished loading. I tried to solve the problem by using performSelectorInBackground, but now data isn't loaded in the cells until I start scrolling. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self performSelectorInBackground:#selector(fethchData) withObject:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
self.listData = nil;
self.plot=nil;
}
-(void) fethchData
{
NSError *error = nil;
NSURL *url=[[NSURL alloc] initWithString:#"http://www.website.com/"];
NSString *strin=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
HTMLParser *parser = [[HTMLParser alloc] initWithString:strin error:&error];
if (error) {
NSLog(#"Error: %#", error);
return;
}
listData =[[NSMutableArray alloc] init];
plot=[[NSMutableArray alloc] init];
HTMLNode *bodyNode = [parser body];
NSArray *contentNodes = [bodyNode findChildTags:#"p"];
for (HTMLNode *inputNode in contentNodes) {
[plot addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
NSArray *divNodes = [bodyNode findChildTags:#"h2"];
for (HTMLNode *inputNode in divNodes) {
[listData addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
//here you check for PreCreated cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
//Fill the cells...
cell.textLabel.text = [listData objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
cell.textLabel.numberOfLines=6;
cell.textLabel.textColor=[UIColor colorWithHue:0.7 saturation:1 brightness:0.4 alpha:1];
cell.detailTextLabel.text=[plot objectAtIndex:indexPath.row];
cell.detailTextLabel.font=[UIFont systemFontOfSize:11];
cell.detailTextLabel.numberOfLines=6;
return cell;
}
Put this somewhere after the data is loaded successfully:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
This fix the problem of calling a GUI update while you're not in the main thread.
This code uses the GCD Technology from Apple to force the reload data function to run on main thread. Read more about
Concurrency Programming Guide for more understanding (it's quite large field so that it's hard to explain in the comment)
Anyway, it's not very recommended if you don't understand it well because it causes the program to crash some rare cases.
For swift 3:
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
For swift 2:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
All you really need to do is any time you have an update to your back-end data, call
[tableView reloadData];
Since this is happening synchronously, you should probably have a function like
-(void) updateTable
{
[tableView reloadData];
}
and after adding the data in your download call
[self performSelectorOnMainThread:#selector(updateTable) withObject:nil waitUntilDone:NO];
U can use [cell setNeedsDisplay];
for example:
dispatch_async(dispatch_get_main_queue(), ^{
[cell setNeedsDisplay];
[cell.contentView addSubview:yourView];
});
I had this problem and I was dealing with it all the day.
I am using static cells and reloadData is causing the wrong loading, it displays only the visible cells and remove the others.
What I noticed is that when I scrolled down (y in negative value) the cells where loaded correctly, so I wrote this code and it worked, even though I don't like to let it in this way.
Shoot if you find any better solution.
-(void)reloadTableView{
CGPoint point = self.tableSettings.tableView.contentOffset;
[self.tableSettings.tableView reloadData];
[UIView animateWithDuration:.001f animations:^{
[self.tableSettings.tableView setContentOffset:CGPointMake(point.x, -10)];
} completion:^(BOOL finished) {
[UIView animateWithDuration:.001f animations:^{
[self.tableSettings.tableView setContentOffset:point];
} completion:^(BOOL finished) {
}];
}];
}
I was having the exact same problem! I wanted the UITableView to be fully populated before the view controller appeared. Envil's post gave me the information I needed, but my solution ended up being different.
Here's what I did (remodeled to fit the context of the question asker).
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelectorInBackground:#selector(fethchData) withObject:nil];
}
- (void)viewWillAppear {
[tableView reloadData];
}
First, this semi-solved my related problem. I want to round corners of an image in a table cell. Dispatching asynchronously fixed the problem for some but not all of the images. Any ideas?
Second, I think you are supposed to avoid creating a strong reference cycle by using a closure capture list like this:
DispatchQueue.main.async(execute: { [weak weakSelf = self] () -> Void in
weakSelf!.tableView.reloadData()
})
See: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID52
I experienced the same issue when using self-sizing cells, and I found that setting the estimatedHeight to 50 would fix the problem.
Set estimatedHeight on the tableView itself or return an estimate from estimatedHeightForRowAt in your UITableViewDelegate.
It seems to work as long as the estimate is more than 0.