I have tried to hide my tableView when it's empty using following line of code inside of the viewDidAppear and viewDidLoad methods:
let count = self.fetchedResultsController.fetchedObjects?.count == 0
self.tableView.isHidden = count
But it's doesn't work.
How to hide a tableView when it's empty?
Do you really need to hide the table when it's empty?
I would rather provide one big table row with information like 'No results found' or something.
But if you need to display other UI stuff when no results:
Try to use the function with fetchRequest.
let count = managedContext.countForFetchRequest(fetchRequest, error: nil) == 0
Related
I'm the beginner of UITests. Currently, I have an issue that I can not access element inside collectionViewCell.
My UI elements structure:
UIViewController
UITableView
-- UITableViewCell
---> UICollectionView
----> UICollectionViewCell
-----> The element that I would like to get.
I've tried with the code below:
let tableCellContainer = app.tables["HomeRVMPTableView"].cells.element(boundBy: 0) // Get the first Cell of TableView
let collectionContainer = tableCellContainer.collectionViews["ContainerItemCollectionView"].cells.element(boundBy: 1) // Get the second Cell inside collectionView
let collectionElement = collectionContainer.staticTexts["BuyCashCard"]
XCTAssertFalse(!collectionElement.exists) // FAILED
Is there any way to access collectionViewCell/tableViewCell easier? I'm so tired when start working UITests with that.
Thank you guys for helping me, I just found another way to access the collection view inside the tableview.
Here is my code:
let tableCellContainer = app.tables["MainTableView"].cells.element(boundBy: 1)
let cell = tableCellContainer.staticTexts["Brazil"]
cell.tap()
XCTAssert(cell.exists)
Hope this will help another guy who has the same issue like me.
For that line to fail, the collectionElement must actually exist. Replace your failing line with XCTAssert(collectionElement.exists)
XCTAssertFalse fails when the condition is true. XCTAssert (equivalent to XCTAssertTrue) succeeds when the condition is true.
func convertPointToIndexPath(_ point: CGPoint) -> (UITableView, IndexPath)? {
if let tableView = [tableView1, tableView2, tableView3].filter({ $0.frame.contains(point) }).first {
let localPoint = scrollView.convert(point, to: tableView)
let lastRowIndex = focus?.0 === tableView ? tableView.numberOfRows(inSection: 0) - 1 : tableView.numberOfRows(inSection: 0)
let indexPath = tableView.indexPathForRow(at: localPoint) ?? IndexPath(row: lastRowIndex, section: 0)
return (tableView, indexPath)
}
return nil
}
So i got this method, which converts a CGPoint into the indexPath of the given uitableView. I struggle with the filter-Method on the array which contains uitableViews.
I got an array outside of this method which contains any number of uitableViews. For example:
public var littleKanbanColumnsAsTableViews: [UITableView] = []
So i got to make a change inside of the method. Like this:
if let tableView = littleKanbanColumnsAsTableViews.filter({ $0.frame.contains(point)}).first { ... }
Now when i click on any tableView on the gui, i track the coordinates of the point and transform it on the belonging tableview with the frame.contains(point) method.
My problem is that the filter is not working, it always gives me the first tableView back, no matter which tableview is clicked. Why it doesn't work with my littleKanbanColumnsAsTableViews-Array?
One hint:
let tableView = littleKanbanView.littleKanbanColumnsAsTableViews[3]
When i indexing its direct then it works. But i want it depending on which tableView is containing the clicked point.
Here is my array with the tableViews, in this case the array contains 5 tableviews.
array containing tableviews
Now i want to filter the tableView out of them, which includes the point from tapping on this tableView. How can i achieve this?
For more understanding, i add the ui, here is it:
UI of my app
When i click on this tableView it works, because it is the first element in my array of tableViews. So for this case the convertPointToIndexPath-Method is working.
But when i scroll horizontally to the second tableView for example and click on that, it doesn't work. Because I think the method gives me always the first element back, but i thought it filters it with the given condition.
What is the problem, why doesn't work the condition{ $0.frame.contains(point)}? It have to localize the tableView when the coordinates of the point are tracked.
Preferred Solution:
In this case the moment the first satisfying condition is met, the rest of the elements are not traversed.
if let tableView = littleKanbanColumnsAsTableViews.first(where: { $0.frame.contains(point) }) {
}
Not so efficient solution:
In this case all the elements in the array are traversed to build an array of table views that satisfy the condition. Then the first element of that filtered array is chosen.
if let tableView = (littleKanbanColumnsAsTableViews.filter{ $0.frame.contains(point)}).first {
}
I have some code right now that gets what cells were selected. The following is my code for doing that:
if let selectedUserRows = self.tableView.indexPathsForSelectedRows {
self.groupUserArray.append(selectedUserRows)
for index in selectedUserRows {
let text = groupUserArray[index.row]
print(text)
}
}
The new error is saying that the index is out of range!
I was trying to use the logic for grabbing one selected cells text but it does not work. So I was wondering if anyone knew how to grab multiple selected cell's text?
Any help would be appreciated!
self.tableView.indexPathsForSelectedRows returns a [IndexPath]? so if you obtain an array of all the rows and sections of you selected rows. I suppose you are using some sort of collection to populate your tableView (in my example I will call it textArray: [String] ) so you can do something like that to get all the text you need:
if let selectedUserIndexes = self.tableView.indexPathsForSelectedRows {
for index in selectedUserIndexes {
let text = textArray[index.row]
}
}
I know this is a startlingly stupid question, but I can't figure it out. Every answer involves a UISearchBar, which is not what I've got.
I'm trying to display 2 sets of results on one TableViewController.
Results to display
1) everything in my managedObjectContext which is set up in my viewDidLoad
2) a filtered set of results if a predicate is selected.
On MyTableViewController, I have a popover which instantiates when I click a UIBarButtonItem on MyTableViewController. On the popover, I set a predicate on MyTableViewController.
Basically, I'd like to toggle what's displayed and that display toggle is driven by whether my variable is nil (everything displays) or filtered (variable sets a predicate).
Have two NSArray properties allValues and filteredValues. Set up all your delegate/dataSource properties using your filteredValues array.
Next, do something like this when you first get all your data:
self.allValues = [someController fetchAllValues];
self.filteredValues = self.allValues;
[self.myView.tableView reloadData];
Last, alter your filteredValues array whether or not a predicate is selected:
if (self.selectedPredicate) {
self.filteredValues = [self.allValues filteredArrayUsingPredicate:self.selectedPredicate];
} else {
self.filteredValues = self.allValues;
}
[self.myView.tableView reloadData];
I have a UIPageViewController with a page control. In the delegate, I implement the following methods:
presentationCountForPageViewController:
presentationIndexForPageViewController:
This works well, but the total number of pages can change, and the number of dots displayed in the page control doesn't change in this case.
How do I tell the page view controller to call presentationCountForPageViewController: to update the total number of dots when this happens?
So it turns out this was a result of using NSFetchedResultsController as the source of the data for pages. The count for NSFetchedResultsController was not getting updated before I called setViewControllers:direction:animated:completion: on the UIPageViewController.
The fix was to call the following function in controllerDidChangeContent: to force an update to the page control.
func refreshPageController() {
let controllers = pageController.viewControllers
if controllers.count > 0 {
pageController.setViewControllers(controllers, direction: .Forward, animated: false, completion: nil)
}
}
Update:
Though the solution above worked, it broke the animation I was using to scroll to the next page when a page was removed.
A better solution: just wait until the page removal is committed to Core Data before calling setViewControllers:direction:animated:completion:.
I had the same problem, and the workaround I found is to reset the uipageviewcontroller view every time I change my dataSoure and reload the whole pageViewController with the new dataSource. This way I'm able to have the correct number of dots (with the dataSource and delegate functions correctly implemented). I do this with the following function :
func reloadPageViewController() {
if pageContentView.subviews.count > 1 {
for _ in 1...pageContentView.subviews.count - 1 {
pageContentView.subviews.last?.removeFromSuperview()
}
}
guard let pageViewController = storyboard?.instantiateViewController(identifier: String(describing: PageViewController.self)) as? PageViewController else {
return
}
pageViewController.removeFromParent()
self.configurePageViewController()
}
Set the dataSource property again to a new instance of a data source object that has the new number of objects.