Im very newbie to iOS programming.
I have core data app for tasks with two entities: Group and Task.
User creates task groups like Work, Home, Shoping and tasks related to these groups like for Work-Deploy an app, for Shopping-buy milk etc.
I have two view controllers.
Problem is that now when user clicks on a Group in tableView, it gets to next viewController, where tasks from all groups are listed. So, how I could show only Group (selected in tableView) related Tasks?
For now when for exapmle I click on Work group I see Deploy an app and Buy milk etc tasks.. I guess its something wrong with NSFetchRequest or NSPredicate Thanks!
Create an NSPredicate to have task == the task from selected cell. Use this predicate filter the the NSSet that you get when asking for the tasks property on the group-class.
If you already did this, please show the code that is doing this, so we can see what exactly is that is going wrong.
Can you also give a screenshot of (the relevant part of) your model and indicate whether you have NSManagedObject subclasses for the entities?
Related
I have an app that had a TableView with customer information.
If a click on a cell I load the detail of this customer.
I'm using Magical Record to manage all my entities.
What I'm doing:
1) Load all the CUSTOMER entity on the viewDidLoad of my TableView.
2) User click to see the detail of the customer
3) Pass to the ViewController of the detail the object that represent the entity CUSTOMER (only one).
Everything works well.
The problem is, if the user select to reload the TableView I do this:
1) Go to the API to get all the customers
2) [Customer truncateAll]
3) Create all the entities back on CoreData
5) [[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait]
6) Reload tableview
BUT, if the user click to see the detail of the Customer during this process, the following ViewController show the customer information correctly for a while. Then after
[Customer truncateAll] occurs all the information dies.
How can I prevent this?
Many thanks!
You can make use of NSFetchedResultController to listen for your Customer entity changes. When your API call finishes and you create proper entities somewhere else in your app, you'll be notified in the controller about those changes and then you can reload the data. If you're not familiar with this concept look here.
I am developing an app that fetches data from the web and displays it to the user. Assume that the data is reviews of a restaurant and one review is displayed on one view. The user can swipe left or right to go to the prev/next review. The data is fetched asynchronously (one thread for each review).
Here is the problem statement - Assume that 5 reviews have been fetched and the user is looking at the 3rd one currently. Now, the 6th review is fetched and I want to display it as the 4th review to the user (because the publish date of the 6th review is more recent than the 5th review). How should my model class inform the view controller?
I have considered some options -
Provide an array to the view controller and then send NSNotifications about new items to be inserted in-between the array at a specific index
Use an NSFetchedResultsController (this is a bit tricky because I am not using it with a table view controller)
View controller always asks for the next review to be displayed (from the model) and does not have a array of reviews with it
Are there any established design patterns that are employed in such a scenario? Other suggestions apart from the 3 above are welcome!
Just use an NSFetchedResultsController. When using NSIndexPaths just ignore the section. It's basically a glorified NSArray with free notifications.
Here's how I think I'd do it:
Make sure that the NSFetchRequest for your NSFetchedResultsController is sorted by publish date.
Handle NSFetchedResultsControllerDelegate methods.
When the NSFetchedResultsController updates, save the current object, reload the collection view, and then scroll to the saved object without any animation. This will appear to the user as if nothing happened to the current page.
While there is no perfect design pattern for every programming problem, the closest I can think of that relates to your problem is a combination of the Command and Observer patterns.
https://en.wikipedia.org/wiki/Command_pattern
The observer pattern is used in the NSNotification center.
While it's unclear as to why you'd want to skip a review, you could have two arrays to store them when fetched. The first holds all reviews that you have fetched. The second holds all reviews that are displayed.
Then you can get the last review in the fetched array, as if it were a stack. This way you always have the last one loaded displayed to the user.
I am confused why the order of display is different than the true order, ie why the 6th review comes before the 5th, but you asked about patterns to help.
Apart from MVC and observer, which are in the other answers and comments, I'd suggest using lazy loading with a virtual proxy. When reviews have been fetched, you can just display their proxy (eg with a "loading..." Message until they're fully in memory).
See more here: http://en.wikipedia.org/wiki/Proxy_pattern
I would recommend using the observing pattern to inform your controller than new data as been fetched. When receiving the signal, your view controller could update its array of "restaurant review" (either by adding the old one and reordering it according to some sort descriptors of your flavor or by querying the DAO directly).
Let's say you are fetching your data from internet and populating a CoreData entity with the results. Once you got your downloaded data you can populate your core data "Review" entity.
In order to "listen" at the change happening in core data, your controller should, in the viewDidLoad body, register itself as an observer for the NSManagedObjectContextDidSaveNotification.
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(updateInfo:) name:NSManagedObjectContextDidSaveNotification object:nil];
Then in your updateInfo, you can get the changes
- (void) updateInfo:(NSNotification *)notification
{
self.reviews = [self.managedObjectContext performRequest:myFetchRequest error:nil];
}
My app will have a tableview with a picture and a title on each row, when the user taps it, it will open another view with that title, some texts and some pictures.
Now, I want each user to have different items in the tableview. For making it easier, suppose it is going to be a todo list like this:
Wash the car (Picture1) (video1) (InstructionsText)
Go to the groceries store (Pic2) (Vid2) (instrText2)
Pay the Bills (Pic3) (Vid3) (instrText3).
Now, I want to assign these items differently for each user, and show in a tableview.
USER 1 TABLE VIEW
Wash the car (Picture1) (video1) (InstructionsText)
Pay the Bills (Pic3) (Vid3) (instrText3).
USER 2 TABLE VIEW
Pay the Bills (Pic3) (Vid3) (instrText3).
USER 3 TABLE VIEW
Wash the car (Picture1) (video1) (InstructionsText)
Go to the groceries store (Pic2) (Vid2) (instrText2)
...
Now, here's my idea: each of these tasks should open a view controller with pictures, videos and text related to them. Using Core Data, I could create a modal, a entity called TodoList and attributes like title, text. First question: Can I create attributes for videos and pictures as well and store them here?
Suppose I have 500 different tasks, I will have to create a view controller for each, right? How would I relate these tasks to each user, like the example above? So each user would have his own tableview with the tasks leading to view controllers.
Assuming it is possible to make this work, how could I change the tasks assigned to each user directly, without having to use xcode or doing it programatically?
Use Core Data to store all your required fields in which image and video can also reside in Core Data. Use predicate to fetch the data according to constraints imposed on each user. When he will open the app, app should be able to fetch data according to user condition. After this you can load your table.
Hope this helps.
If we consider TO-DO apps , if a user should be able to see his own content , he will have to enter his own content through the app.This data is then stored in some backend either Core Data , SqLite or even cloud backend like Parse.com.Then the user is able to fetch his data , and see the contents in any view ...like tableView in your case.
I'm struggling with some aspects of Core Data, namely setting up a UITableView to list data from a to-many relationship.
I have three entities, Teams, TeamDetails and Players:
In the first view, I list the names of all the teams in the Teams entity, then tapping each cell segues to an intermediate view with buttons to either edit a team's details or edit a team's players. Tapping on a button segues to another UITableView that lists the Team's details or Players.
Listing the TeamDetails works, since it is a one-to-one relationship and a static cell table.
I'm trying to set up a UITableViewController that lists all the players that are associated with the selected team. So I pass the ManagedObjectContext etc to the table view controller via the segue as shown below:
else if ([segue.identifier isEqualToString:#"ShowPlayersSegue"]){
NSLog(#"Setting ShowPlayersTVC as a delegate of EditPlayerTVC");
ShowPlayersTVC *showPlayerTVC = segue.destinationViewController;
showPlayerTVC.delegate = self;
showPlayerTVC.managedObjectContext = self.managedObjectContext;
showPlayerTVC.team = self.team;
showPlayerTVC.player = self.team.playerDetails;
}
So, in my showPlayerTVC I want to get the set of players for that specific team, then have a row for each one that shows the playerName attribute as the cell textlabel.text.
I've been reading tutorials and playing around for ages without getting much success. I think I need to create an array of Player objects from the NSSet, which I can do, but I can't get the UITableview to list the objects. I'm probably missing something fundamental here, but any suggestions would be appreciated.
First, there are some issues with your data model.
The one-to-one to details I do not understand - why not just add attributes to the Team entity? Also, you may want to transform some of these into more flexible relationships, such as a Trainer entity, etc.
Also, your naming is flawed and will lead to programming errors or at least make your code difficult to read. Note the singular / plural confusion. Here is my suggestion for naming your entities / relationships:
Team - players <--------------->> team - Player
To display data in an a table view you should use NSFetchedResultsController. Let the FRC fetch the Player entity and give its fetch request the following predicate:
[NSPredicate predicateWithFormat:#"team = %#", teamObject];
Your segue code is almost correct. Give the new view controller a team attribute and use this in the above predicate of its fetched results controller. You do not need any player or "playerDetails" information (they are linked to the team anyway).
I have an NSFetchedResultsController to display a tableView.
And users are allowed to change the cells' order.
How can I record the order so that when users go to the view again,
the table displays by the order modified by users last time?
Thanks a lot!
Hey guys I've done this.
In order to re-order managedObjects fetched by a fetchedResultsController, the most official way I think is to give the entity another attribute of int, such as "order", and give this attribute to the fetch request of a fetchedController, and in table view delegate method "move row from .. to " something like that, deal with this attribute with your hands, and if you use a fetchedController delegate, set a flag in that delegate methods to indicate that you will modity the entity yourself, and notify the delegate to do nothing but return.
Sample codes are Apple Sample code Recipes, and hints on the documentary of fetchedController!