3lvis / datasource Goto Github PK
View Code? Open in Web Editor NEWCore Data's NSFetchedResultsController wrapper for UITableView and UICollectionView
License: Other
Core Data's NSFetchedResultsController wrapper for UITableView and UICollectionView
License: Other
self.dataSource.predicate
self.dataSource.fetchedResultsController.fetchRequest.predicate
self.dataSource.objectsCount
self.dataSource.fetchedResultsController.fetchedObjects?.count
self.dataSource.object(indexPath: NSIndexPath)
self.dataSource.fetchedResultsController.objectAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as? Song
self.dataSource.indexPath(object: NSManagedObject)
self.dataSource.fetchedResultsController.indexPathForObject(song)
self.dataSource.objects
self.dataSource.fetchedResultsController.fetchedObjects!
self.dataSource.isEmpty?
{if self.dataSource.fetchedResultsController.fetchedObjects?.count == 0 {
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#")
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - reorder / moving support
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
The readme shows the following two methods as examples, but the library actually includes a mainContext param in the two DATASource initializers.
DATASource *dataSource = [[DATASource alloc] initWithTableView:self.tableView
fetchRequest:fetchRequest
cellIdentifier:ANDYCellIdentifier
configuration:^(UITableViewCell *cell, Task *task, NSIndexPath *indexPath) {
cell.textLabel.text = task.title;
};
DATASource *dataSource = [[DATASource alloc] initWithCollectionView:self.collectionView
fetchRequest:fetchRequest
cellIdentifier:ANDYCellIdentifier
configuration:^(UICollectionView *cell, Task *task, NSIndexPath *indexPath) {
cell.textLabel.text = task.title;
};
The actual methods are:
- (instancetype)initWithTableView:(UITableView *)tableView
fetchRequest:(NSFetchRequest *)fetchRequest
cellIdentifier:(NSString *)cellIdentifier
mainContext:(NSManagedObjectContext *)mainContext
configuration:(void (^)(id cell,
id item,
NSIndexPath *indexPath))configuration;
- (instancetype)initWithCollectionView:(UICollectionView *)collectionView
fetchRequest:(NSFetchRequest *)fetchRequest
cellIdentifier:(NSString *)cellIdentifier
mainContext:(NSManagedObjectContext *)mainContext
configuration:(void (^)(id cell,
id item,
NSIndexPath *indexPath))configuration;
Make sure that we get the correct title here
public var objects: [NSManagedObject]
Firstly, thank you so much for this library! I've been messing with NSFetchedResultsController + Sections for days now and this just solved all my problems - except one... For some reason I can't get a custom UITableViewCell cell subclass (in Storyboards) to work with this library.
Any help would be much appreciated.
Thanks in advance!
Inspiration: BDKCollectionIndexView
Some times we want to entirely change the cell and load it from different xib or etc. at specific situations but this cool framework limits cell identifier to just one static reusable cell. I'm very interested to know is there a good reason behind this?
Thanks
Not super critical, but would be great if DATASource
could support more than one cell.
Like if you had a list of members and the owner of the group gets presented using a different cell.
In case the new predicate change amount of items, collection view crashed:
2017-05-12 11:23:26.192 SwiftDemo[12755:330575] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (14) must be equal to the number of items contained in that section before the update (16), plus or minus the number of items inserted or deleted from that section (10 inserted, 10 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'
To repeat this issue just add to Swift Demo project inside one of CollectionViewController:
func saveAction() {
Helper.addNewUser(dataStack: self.dataStack)
self.dataSource.predicate = NSPredicate(format: "role == %@", "manager")
}
Possible solution (rollback "Safer UICollection reloading") in Merge Request โ #103
DATASource has an animations
variable, would be great to know how to use it.
Hi!
Due the fact that I could not override func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]?
I forked your repo and create a argument in constructor ti disable section index, because I really dont need one in my app, I twisted it only for Swift UITableView as you can see here: https://github.com/AJTY/DATASource/commit/8fe934ebd44d82712c61ee26ecfa12cd5e4bcdbf
In case this is something you would like to have in your project, you can either think of better way how to do that, or I can get it done for all other usage of DATASource and then I can create pull request.
Let me know, if you want me to help you with this or if you are even interested in it. In case I was doing something wrong and I did not needed to do that to achieve what I wanted, throw on me all the dirt you have.
Thanks Syky.
Implementing
- (NSArray *)sectionIndexTitlesForDataSource:(UITableView *)tableView;
- (NSInteger)dataSource:(UITableView *)tableView
sectionForSectionIndexTitle:(NSString *)title
atIndex:(NSInteger)index;
should be way easier.
If you're already calling it in willDisplay
you want to avoid calling it again.
Is it possible to filter DataSource using UISearchBar?
I'm trying but without success. Any help will be appreciated.
Thanks.
Hi, I have rather big problem, when I use DATASource to place fetched objects from Core Data to UITableView with sections, some of the objects will get placed to wrong section.
I am using following code:
lazy var dataSource: DATASource = {
let request: NSFetchRequest = NSFetchRequest(entityName: "TypicalFindingDescription")
request.sortDescriptors = [NSSortDescriptor(key: "materialRemoteID", ascending: true)]
let dataSource = DATASource(tableView: self.tableView, cellIdentifier: TypicalDescriptionTableViewCell.Identifier, fetchRequest: request, mainContext: self.dataStack.mainContext, sectionName: "materialName", configuration: {
cell, item, indexPath in
if let name = item.valueForKey("name") as? String, let materialName = item.valueForKey("materialName") as? String, let materialRemoteID = item.valueForKey("materialRemoteID") as? Int {
if let cell = cell as? TypicalDescriptionTableViewCell {
cell.textLabel!.text = name
cell.textLabel!.lineBreakMode = .ByWordWrapping
cell.textLabel!.numberOfLines = 0
}
}
})
return dataSource
}()
I triple checked that the data are correctly stored in Core Data.
This actually occurs on two different Entities, according to my testers, but I haven't checked the other one.
Thank you for any help.
2016-04-25 09:11:29.978 iOS Development[2277:52401] *** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.60.7/UICollectionView.m:4422
2016-04-25 09:19:24.460 iOS Development[2277:52401] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to delete item 24 from section 0 which only contains 22 items before the update with userInfo (null)
Hello @3lvis
Can you help me to implement DidSelectRowAtIndexPath of TableView please??
I think that it would be useful to expose some delegate to enable setting custom messages when table view is empty (sorry if this is already possible, but I could not find how). Currently I am using something like this: http://stackoverflow.com/questions/28532926/if-no-table-view-results-display-no-results-on-screen
To get it working here ,while using this pod, I added a new delegate (you can check here: https://github.com/guilhermekrz/DATASource/commit/c94e89dcfe291b105fdc07d408bf1b60a40850de).
However I don't think that this is the best way to expose this. Any ideas?
Hi Elvis!
I'm trying to customize animations in Objective C, but I can't get to access the dictionary for animations. How I accomplish this?
I love this library BTW.
My Model
MyViewController
@property (nonatomic) DATAStack *dataStack;
@property (nonatomic) DATASource *dataSource;
@property (nonatomic) DATASource *dataSourceCollection;
.
.
.
- (DATAStack *)dataStack
{
if (_dataStack) return _dataStack;
_dataStack = [[DATAStack alloc] initWithModelName:@"Model"];
return _dataStack;
}
- (DATASource *)dataSource
{
if (_dataSource) return _dataSource;
_dataStack = [self dataStack];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Program"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"remoteID"
ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:@"f2fEvent.remoteID == %@", self.event.remoteID];
_dataSource = [[DATASource alloc] initWithTableView:self.tableView
fetchRequest:request
cellIdentifier:@"SyncProgramCell"
mainContext:self.dataStack.mainContext
configuration:^(UITableViewCell *cell,
Program *item,
NSIndexPath *indexPath)
{
//Implementing Cell
}];
return _dataSource;
}
-(DATASource*)dataSourceCollection
{
if(_dataSourceCollection) return _dataSourceCollection;
if (!_dataStack) {
_dataStack = [self dataStack];
}
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Place"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"profile"
ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:@"f2fEvent.remoteID == %@", self.event.remoteID];
_dataSourceCollection = [[DATASource alloc] initWithCollectionView:self.collectionView
fetchRequest:request
cellIdentifier:@"SyncProfileCount"
mainContext:self.dataStack.mainContext
configuration:^(id cell, Place *item, NSIndexPath *indexPath)
{
// Implemantation Cell
}];
return _dataSource;
}
-(void)registerTableViewCell
{
UINib *nib = [UINib nibWithNibName:@"ViewF2FDetail"
bundle:[NSBundle mainBundle]];
UINib *nibCollection = [UINib nibWithNibName:@"SyncPlaceCell"
bundle:[NSBundle mainBundle]];
//Add TableViewCell Config
[self.tableView registerNib:nib
forCellReuseIdentifier:@"SyncProgramCell"];
//Add CollectionViewCell Config
[self.collectionView registerNib:nibCollection
forCellWithReuseIdentifier:@"SyncProfileCount"];
// [self.collectionView registerClass:[JRProfileCollectionViewCell class]
// forCellWithReuseIdentifier:@"SyncProfileCount"];
}
-(void)viewDidLoad
{
[super viewDidLoad];
[self registerTableViewCell];
[self.tableView setDataSource:self.dataSource];
[self.tableView setDelegate:self];
[self.collectionView setDataSource:self.dataSourceCollection];
.
.
.
}
I do understand as this ins possible
I see #25 but this error is not
You can group by firstLetterInString, day, year, month, group by attribute
// The view that is returned must be retrieved from a call to -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
Hey 3lvis,
i need to change the predicate when text change called on e.g. SearchBar. But there is no way to access the fetchedResultController to update the predicates!
What i need is something like this:
let frc = myDataSource.fetchedResultsController
frc.fetchRequest.predicate = NSPredicate(format: "firstname CONTAINS[cd] %@", searchString)
try! frc.performFetch()
tableView.reloadData()
When using sortDescriptors with sectionName, the sectioName descriptor has to be in the top, this is a stupid bug by NSFetchedResultsController.
Wrong:
let request: NSFetchRequest = NSFetchRequest(entityName: "User")
request.sortDescriptors = [
NSSortDescriptor(key: "count", ascending: true),
NSSortDescriptor(key: "name", ascending: true),
NSSortDescriptor(key: "firstLetterOfName", ascending: true)
]
let dataSource = DATASource(tableView: self.tableView, cellIdentifier: CustomCell.Identifier, fetchRequest: request, mainContext: self.dataStack!.mainContext, sectionName: "firstLetterOfName") { cell, item, indexPath in
}
Correct:
let request: NSFetchRequest = NSFetchRequest(entityName: "User")
request.sortDescriptors = [
NSSortDescriptor(key: "firstLetterOfName", ascending: true),
NSSortDescriptor(key: "count", ascending: true),
NSSortDescriptor(key: "name", ascending: true)
]
let dataSource = DATASource(tableView: self.tableView, cellIdentifier: CustomCell.Identifier, fetchRequest: request, mainContext: self.dataStack!.mainContext, sectionName: "firstLetterOfName") { cell, item, indexPath in
}
I want show custom message when table view is empty, but it always return 1, even if theres is no data.
public func numberOfSectionsInTableView(tableView: UITableView) -> Int {
print(self.fetchedResultsController.sections?.count)
return self.fetchedResultsController.sections?.count ?? 0
}
But, when i use this function without implementing DATASource, just in my own table, it returns correct count of sections:
public func numberOfSectionsInTableView(tableView: UITableView) -> Int {
print(self.fetchedResultsController.sections?.count)
return self.fetchedResultsController.sections?.count ?? 0
}
Can't find any explanation for that.
I'm trying DATASource in a project and it doesn't seem to work.
I setup the DATASource object accordingly:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Session"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
NSManagedObjectContext *context = [[CodecampDataStack sharedStack].dataStack mainContext];
DATASource *dataSource = [[DATASource alloc] initWithTableView:self.tableView
cellIdentifier:kSessionTableViewCellReusableIdentifier
fetchRequest:request
mainContext:context
sectionName:nil
configuration:^(UITableViewCell * _Nonnull cell, NSManagedObject * _Nonnull item, NSIndexPath * _Nonnull indexPath) {
cell.textLabel.text = [item valueForKey:@"name"];
}];
self.tableView.dataSource = dataSource;
But it seems that the tableView delegate methods (inside DATASource) are not called.
calling po dataSource.objectsCount
returns, as expected, 67.
Project can be found here: https://github.com/cyupa/Codecamp-iOS
UITableViewClass: SessionsTableViewController.
Is it possible to implement lazy loading rows with DATASource because?
Thanks.
Hey 3lvis,
can you please share an example to delete and refresh cells in table-view like:
extension MyViewController:DATASourceDelegate {
func dataSource(_ dataSource: DATASource, tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: IndexPath) {
tableView.beginUpdates()
if editingStyle == .delete {
tableView.deleteRows(at: [indexPath], with: .automatic)
}
tableView.endUpdates()
}
func dataSource(_ dataSource: DATASource, tableView: UITableView, canEditRowAtIndexPath indexPath: IndexPath) -> Bool {
return true
}
}
Thank you.
Regards
Peter
Potentionaly really stupid question. Does this work with custom UITableViewCell? If so, can you please give me any hint. I cannot get it working. Thanks!
Transient property for sectionName does not supported for now.
When I use 'firstLetter' (transient property) as sectionName in DATASource initializer I got error:
'Invalid keypath firstLetter passed to setPropertiesToFetch:'
There is an issue in default implementation of UIDataSourceTableView.sectionIndexTitlesForTableView:. I suppose this method should detect is property transient and should not execute request when property is transient. Or maybe this metnod should notify developer somehow that when using transient property he must implement DATASourceDelegate.sectionIndexTitlesForDataSource: in this case.
For some background related to this issue please see: https://stackoverflow.com/questions/11432556/nsrangeexception-exception-in-nsfetchedresultschangeupdate-event-of-nsfetchedres
I have UIViewController with one UITableView and 3 lazy instances of dataSource and one optional that indicates activeDataSource for my tableView. Each dataSource has own predicate, sortDescriptor. I also added UISegmentedControl with 3 segments for each data source and function that will change activeDataSource and reload data. Every time viewDidLoad() i have function, that fetches data from server and sync it with Core Data and it can take 3-4 seconds. This 3-4 seconds i try randomly tap segmentedControl to change my dataSource and i get error:
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.7/UITableView.m:1502
2016-05-19 09:43:19.702 MyApp[9301:2958707] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update with userInfo (null)
Yes, i can disable UserInteraction on segmentedControl, but sometimes user doesn't like wait for sync completion and just filter data, that he/she wants.
In addition i want implement searchController, that will need 4th dataSource, and it will filter data more faster.
Any idea, how avoid this error?
In the indexed list ร appears just after A, when it should go after Z.
request.sortDescriptors = [NSSortDescriptor(key: keyPath, ascending: true)]
If a keyPath is provided, you should also be able to say if it's ascending or descending.
Add a demo that shows how to use DATASource with cells that have different styling
Add a demo that shows how to:
Sorry if the wrong forum, as this isn't a problem.
I've used DATASource in another project and loved it. On a new project, I'm using Realm as the persistent layer. I've seen some things on the Realm side that do things to replicate NSFetchedResultsController. However, I haven't seen anything yet that does as nice a job as DATASource on the Realm side of things. It could be that I'm just not looking in the right place. But if you knew of a Realm equivalent of DATASource, I'd be happy to hear about it.
don't work
if ([self.delegate respondsToSelector:@selector(dataSource:canEditRowAtIndexPath:)]) {
[self.delegate dataSource:tableView
canEditRowAtIndexPath:indexPath];
}
Hi, according to README by doing this:
func sectionIndexTitlesForDataSource(dataSource: DATASource, tableView: UITableView) -> [String] {
return [String]()
}
You can get rid of those indexes, that is correct and it works great but, in my app this causes memory leak.
Can you please check your app using this? It might me my mistake, but right now I am not sure at all.
Thanks
Hi! No matter what I do I cannot get this to work.
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let block = UITableViewRowAction(style: .Normal, title: "Block") { action, index in
print("Block")
}
let delete = UITableViewRowAction(style: .Default, title: "Delete") { action, index in
print("Delete")
}
return [delete, block]
}
func dataSource(dataSource: DATASource, tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func dataSource(dataSource: DATASource, tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
}
IMHO you are missing something like this
func dataSource(dataSource: DATASource, tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
In case not, please correct me.
Thank you!
Hi,
I'm loading a list of locations in tableView. I have a model with fields "latitude" and "longitude" and I want to sort this list by distance using my current location. How can I sort dataSource?
Thanks.
Hi, I have been using DATASource for a hile now with Sync, in my project everything works fine in iOS 9, but testing in iOS 8.4 throws an EXC_BAD_ACCESS on public func controllerDidChangeContent
specifically on tableView.endUpdates()
. Could you guide me in what can be wrong? Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.