I have a very simple Core Data app which pretty much contains strings of text. I would like to make this text searchable, and can see a "Search Bar and Search Display Controller" object in Interface Builder.
Firstly, would using this Search Bar and Search Display Controller be the best approach for a simple Core Data-driven text search? Secondly, could you point me to some resources which would get me started? Possibly a nice step by step guide or a sample project – the simpler the better.
I have looked both on SO and the Apple iPhone Dev Center but I can't seem to find anything. Thanks again!
This is how I did it.
When the delegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
tells me the user typed something in the search bar, I create a predicate
[NSPredicate predicateWithFormat:#"string CONTAINS[c] %#",searchText];
fetch the results from the MOC with this predicate, update my results array and tell the results table view to reload
[[self.searchDisplayController searchResultsTableView] reloadData];
If you have a lot a results you can try setting a fetch limit, and load all the results if the user presses the search button.
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar;
Hope this helps.
Related
I have a working iPad app, that uses Core Data, a SplitView, and uses the Master-Detail pattern. Think of it like the Apple messaging app, where you have a list of conversations in the root view controller, and when you select a conversation, all its messages appear in the DetailViewController.
I use a searchBar in the RootViewController, and since I use the UISearchDisplayDelegate and UISearchBarDelegate protocols, I use handleSearchForTerm to update my search results as the user types each character of their search words.
All this works really well.
Here is my problem. There is a thread that fetches data from the internet, and records can be added or removed from Core Data, while my search results are being displayed.
Before you have to ask, the thread does all its adds and deletes on the main UI thread, calling methods with performSelectorOnMainThread. So the search, adds and deletes occur in the same managedObjectContext.
So what happens is that I do a search, and results appear. Meanwhile, an update occurs, and one of the records in the result set gets deleted. Now, there's a mismatch between the results and their indexPath.
My solution would be simple: When I detect that a delete occurs with
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
I want to programmatically cancel the search in the searchBar.
So how do I programmatically cancel a search? If the user clicks "Cancel" in the search bar, everything is fine. How can I programmatically do the same thing?
Any help is appreciated.
Peter
If you want to cancel the search, why not go ahead and use the following UISearchBarDelegate call
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar;
This is assuming that you have the proper code in this location already.
I wan't to creata a "CatchNames" class which I can import into a view Controller that shows a text which asks for text input. I would like to be able to add an instance of CatchNames to my view, have it ask the user for three names in a row and return them in an array.
[self.view addSubview:[catchNames view]];
NSArray *myNamesArray = [catchNames namesArray];
The best way would be to have the application freeze kind of the way it does when you are prompted to enter a password in iOS and continue when the user entered 3 names so I can immediately catch the array in the next line.
While this might not be the best description I still hope you understand my problem.
How can I approach this?
Thank you in advance
I guess you appear to be looking to implement a simple form which gets the user input, retrieves and stores it in an array? Hopefully I haven't misunderstood the question, but this seems to be a simple task you can accomplish with one or more UITextField's and a UIButton as a 'Add' or 'Done' call to action.
Are you looking for some general UI coding level help regarding implementing such a view? If so, I would encourage taking a look at the XCode documentations of UITextField (for capturing text), UIButton (for handling actions) and UIView (for view hierarchy and animation implementation).
Some quick notes;
Looks like 3 names are compulsory, so, you may verify whether a UITextField is empty at the button's click action.
Have the array declared in the view controller, not the view
The 'freezing' you require should take care of itself as long as the view offers no other way out for the user other than clicking the button.
Do excuse me if I am oversimplifying the problem. Let me know if you need me to drill down into anything further.
Cheers!
When I use the TTLauncher to call a TTTableViewController the table is loaded correctly it shows the "Loading..." screen as expected and then the table:
- (void)launcherView:(TTLauncherView*)launcher didSelectItem:(TTLauncherItem*)item {
[[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:item.URL]];
}
However when I call the TTTableViewController from a TTTableSubtitleItem using the URL:
[TTTableSubtitleItem itemWithText:#"Locations Map" subtitle:#"Find a specific location" URL:#"tt://BuildingsLocationTableViewController/Loc"]
the loading screen does NOT show, it waits and then goes directly to the loaded table. Can anyone tell me why these call the TTTableViewController is different ways considering they both map through TTURLMap?
Thanks
JC
The mechanism, as you say, is just the same in both cases.
I would suggest checking your BuildingsLocationTableViewController model definition, and check the isLoadingselector, and the data source titleForLoading selector.
From there, if you debug, you should be able to find out a little more.
I'm using Indexed UITableView by implementing the following delegate methods:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
The index is displayed on the right of the table.
I was wondering if the index can be displayed on the left instead.
Thanks,
You can move the tableView index view to the left, but just a little bit so you don't get your app rejected )). Here is how:
// somewhere in your code for example in table view delegate method add this code
// take the index view, which is the last subview on the tableView
UIView *indexView = [[self.tableView subviews]lastObject];
// now take its frame and play with it
CGRect indexViewRect = indexView.frame;
indexViewRect.origin.x -= 50; // move it to the left by -50
indexView.frame = indexViewRect; // set the new frame
Thats it :)
By the way, I dont think Apple will reject your app if you move the index view to the most left, because I saw this on their contacts app on the iPad, but anyway at your risk.
Update: Fully customizable and easy to use ScrollBar you can find here:
https://github.com/BasheerSience/BRScrollBar
No, the style and position of this index is not configurable (unfortunately).
I don't think the api exposes that component. So sadly, you'd have to suppress rotations and hold the phone upside down, and this would be a very poor user experience. (Just a joke, don't downvote me)
Even not officially exposed by iOS APIs, it should be possible to move the index, by "hacking" a bit.
First you have to locate the the index in the UITableView subviews tree.
One simple way to do this is to put a breakpoint at runtime and use that:
po [myTableView recursiveDescription]
This will print the views tree and by analyzing it you should find a way to programmatically find the UIView that interests you and just move it (view.frame.origin), and that, without using any private API
But before trying this, think twice. That index is on right side for a good reason, most people are right handed with the thumb on that right side... It would be hard to use on other side.
Ok, lemme start out by saying Im new to this! LOL I have done my due diligence of studying the topics (4 books and numerous videos to date) and searching for hours on end, and still havent found an answer.
I feel like I have a solid understanding of Core Data, or at least the back end DB side of it. I have my app built and I have my model built. My app has a Tabbar controller as well as a navigation controller for each separate tab.
My app will have an item table view which populates the name of those items from Core Data. Upon selecting the item, the navController pops to a detail view which loads the rest of the data for that item.
When a user clicks + to add an item, I need to pop to another View Controller with fields to add the name and details (which it does). However, I cant seem to get these details to save. I think I need to cast the user inputs as an NSSet, then bring that NSSet into the persistent store, but the method declaration for this is eluding me! Currently, my code looks like so...
- (IBAction) save:(id)sender {
NSLog(#"Save pressed");
if (itemName != nil) {
[itemName removeObject:itemName];
self.item = nil; //This will release our reference also
}
//Create a new item set for the new values
NSSet* newItem = [[NSSet alloc] initWithSet:newItem];
[self didChangeValueForKey:#"itemName"];
[self didChangeValueForKey:#"detailItem1"];
[self didChangeValueForKey:#"detailItem2"];
//Add it to the master item array and release our reference
[itemArray addObject:newItem];
[newItem release];
//Sort the array since the name might have changed with an existing item or a new one
NSSortDescriptor *nameSorter = [[NSSortDescriptor alloc] initWithKey:#"itemName" ascending:YES selector:nil];
[itemArray sortUsingDescriptors:[NSArray arrayWithObject:nameSorter]];
NSLog(#"Array sorter");
[nameSorter release];
//then pop the detailed view controller
[self dismissModalViewControllerAnimated:YES];
}
All of the documentation I have found on Core Data points more in the direction of populating an already existing database, not accepting user inputs. So if I am WAY off in my approach and the answer is more than just a simple one, please point me in the right direction!!
Also, Ive added items to my Core Data store that successfully persist. However, an sqlite DB hasn't been created in my app, which I thought happened automatically. So I may have more problems than I thought!
So far I have found this site to be a tremendous help, even though my reputation doesnt allow me to rate answers!
Anyway, thanks in advance for the help.
In most Core Data implementations, you don't deal with sets directly unless you are simultaneously adding multiple managed objects to a relationship. I'm not really sure what you are trying to do here.
In the code shown, you don't do anything related to Core Data. You do not have a context and you do not insert into the context a new managed object that you can populate with your new data. In fact, you don't seem to have any managed objects at all.
I suggest you look at the Navigation based project template in Xcode. It shows how to set up the Core Data stack and how to add and remove objects displayed in a tableview.