Mapping between array of enums and a dictionary of enums - ios

Here's what I'm trying to do:
Provide a tableView that allows the user to select a formula name (an enum) that will be set as their default
In this view I'll place a checkmark next to the formula that is the current default
Their chosen default formula is what will determine which formula is used to calculate a 1 rep maximum amount (the theoretical amount the user could lift based on actual lifts of lesser weight)
After calculating the value, the user will be able to save a record of the lifts they did, the formula used to calculate the maximum, and the calculated maximum weight.
That record will be saved in Core Data with one of the entities being Lift which will simply be the formula name
I've created a class that I want to handle the work of providing the current default formula to what ever part of the app needs it as well as set the default when a new one is selected.
Here is my enum of the formula names:
enum CalculationFormula: Int {
case Epley
case Brzychi
case Baechle
case Lander
case Lombardi
case MayhewEtAl
case OConnerEtAl
}
and with help from the SO community, I created this class to handle the management of userDefaults:
class UserDefaultsManager: NSUserDefaults {
let formulas = [CalculationFormula.Baechle, CalculationFormula.Brzychi, CalculationFormula.Epley, CalculationFormula.Lander, CalculationFormula.Lombardi, CalculationFormula.MayhewEtAl, CalculationFormula.OConnerEtAl]
let formulaNameDictionary: [CalculationFormula : String] =
[.Epley : "Epley", .Brzychi: "Brzychi", .Baechle: "Baechle", .Lander: "Lander", .Lombardi: "Lombardi", .MayhewEtAl: "Mayhew Et.Al.", .OConnerEtAl: "O'Conner Et.Al"]
let userDefaults = NSUserDefaults.standardUserDefaults()
func getPreferredFormula() -> CalculationFormula? {
guard NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys.contains("selectedFormula") else {
print("No value found")
return nil
}
guard let preferredFormula = CalculationFormula(rawValue: NSUserDefaults.standardUserDefaults().integerForKey("selectedFormula")) else {
print("Wrong value found")
return nil
}
return preferredFormula
}
func setPreferredFormula(formula: CalculationFormula) {
NSUserDefaults.standardUserDefaults().setInteger(formula.rawValue, forKey: "selectedFormula")
}
You can see I have an array of the enums in the order I want them displayed in the tableView and a dictionary of the enums so I can get each enum's string representation to display in each cell of the tableView. Here's how I populate the cell text label which works:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("formulasCell", forIndexPath: indexPath)
let currentFormula = formulas[indexPath.row].formulaName
cell.textLabel?.text = currentFormula
return cell
}
and here's where I'm setting the checkmark anytime a cell in the tableView is selected
func refresh() {
let preferredFormula = defaults.getPreferredFormula()
for index in 0 ... formulas.count {
let indexPath = NSIndexPath(forItem: index, inSection: 0)
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = preferredFormula == index ? .Checkmark : .None
}
}
}
As I mentioned at the beginning, I need to do many different things with this enum but to keep this question focused on one thing, I'll stay with this checkmark example which now doesn't work after creating my UserDefaultsManager class
The problem is obvious - preferredFormula is now an enum and I can't compare that to the index value which is an Int - but the solution is not. I could get the raw value of the enum but the rawValues aren't guaranteed to be in alignment with the cell indexPaths. Some ideas I've had are:
I could probably change the order of the enum cases so their raw values match the order I've put them in my formulas array, but that seems silly and unreliable
I could use the array index values but that seems equally silly and unreliable
If I just use the array, I don't have the string representations of the cases to display in the cells
It seems that using the array and dictionary together is a viable but the best I could come up with is maybe creating another dictionary that maps the enums to Ints but that would have the same issues I just listed.
Any guidance someone could provide would be greatly appreciated.

You seem to have made things a little more complicated than they need to be.
Firstly, you can use a String raw value for your enum and avoid the associated dictionary:
enum CalculationFormula: String {
case Epley = "Epley"
case Brzychi = "Brzychi"
case Baechle = "Baechle"
case Lander = "Lander"
case Lombardi = "Lombardi"
case MayhewEtAl = "Mayhew Et.Al."
case OConnerEtAl = "O'Conner Et.Al"
}
Second, Your UserDefaultsManager doesn't need to subclass NSUserDefaults, it is simply some utility functions. Also, you are doing a lot of checking in getPreferredFormula that you don't need to. I would suggest re-writing that class to use a computed property like so:
class UserDefaultsManager {
static let sharedInstance = UserDefaultsManager()
private var defaultsFormula: CalculationFormula?
var preferredFormula: CalculationFormula? {
get {
if self.defaultsFormula == nil {
let defaults = NSUserDefaults.standardUserDefaults()
if let defaultValue = defaults.objectForKey("selectedFormula") as? String {
self.defaultsFormula = CalculationFormula(rawValue: defaultValue)
}
}
return self.defaultsFormula
}
set {
self.defaultsFormula = newValue
let defaults = NSUserDefaults.standardUserDefaults()
if (self.defaultsFormula == nil) {
defaults.removeObjectForKey("selectedFormula")
} else {
defaults.setObject(self.defaultsFormula!.rawValue, forKey: "selectedFormula")
}
}
}
}
I have made the class a singleton; although this may have an impact on testability it simplifies issues that could arise if the default is changed in multiple places.
The appropriate place to set/clear the check mark is in cellForRowAtIndexPath so that cell reuse is handled appropriately. This code assumes that formulas is an array of CalculationFormula:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("formulasCell", forIndexPath: indexPath)
let currentFormula = formulas[indexPath.row]
cell.textLabel?.text = currentFormula.rawValue
let preferredFormula = UserDefaultsManager.sharedInstance.preferredFormula
cell.accessoryType = currentForumula == preferredFormula ? .Checkmark : .None
return cell
}

Related

How do I use multiple cells in a tableView using Rx?

I have a tableView with two cells: StaticSupportTableViewCell and SupportTableViewCell. As the name suggests the first cell is a single static cell on top of the tableView. SupportTableViewCell can be any number and should be displayed underneath the static cell.
I have code that binds and returns the correct cell:
viewModel.multiContent.bind(to: tableView.rx.items) { tableView, index, item in
if let cellViewModel = item as? StaticSupportTableViewCellViewModel {
let cell = tableView.dequeueReusableCell(withIdentifier: StaticSupportTableViewCell.identifier) as? StaticSupportTableViewCell
cell?.viewModel = cellViewModel
guard let guardedCell = cell else { return UITableViewCell()}
return guardedCell
}
if let cellViewModel = item as? SupportTableViewCellViewModel {
let cell = tableView.dequeueReusableCell(withIdentifier: SupportTableViewCell.identifier) as? SupportTableViewCell
cell?.viewModel = cellViewModel
guard let guardedCell = cell else { return UITableViewCell()}
return guardedCell
}
else { return UITableViewCell() }
}.disposed(by: disposeBag)
In the viewModel I have the multiContent variable:
var multiContent = BehaviorRelay<[Any]>(value: [])
Now if I accept the cell viewModels onto that relay one by one it works:
This works:
multiContent.accept([StaticSupportTableViewCellViewModel(myString: "TESTING")])
Or doing this instead:
multiContent.accept(mainService.serviceProviders.compactMap { SupportTableViewCellViewModel(serviceProvider: $0, emailRelay: emailRelay)})
But if I try both at the same time...
multiContent.accept([StaticSupportTableViewCellViewModel(myString: "TESTING")])
multiContent.accept(mainService.serviceProviders.compactMap { SupportTableViewCellViewModel(serviceProvider: $0, emailRelay: emailRelay)})
...only the last cell is shown. It's like the last one replaces the first one instead of being an addition to it.
So how do I accept both cell viewModels to the relay so that both are displayed in the tableView?
EDIT
I sort of got it right by adding the two cell viewModels into one array:
let contents: [Any] = [StaticSupportTableViewCellViewModel(brand: name, url: web.localized(), phoneNumber: phone.localized()), mainService.serviceProviders.compactMap { SupportTableViewCellViewModel(serviceProvider: $0, emailRelay: emailRelay)}]
And changed the binding:
if let cellViewModels = item as? [SupportTableViewCellViewModel] {...
This is problematic though as I'm stuck with and array of [SupportTableViewCellViewModel]. It doesn't work looping them and returning the cells as they overwrite one another.
The solution is to send in the cell viewModel SupportTableViewCellViewModel instead of [SupportTableViewCellViewModel], but how do I do that?
A BehaviorRelay only emits the most recent array accepted. When you call accept(_:) you aren't adding to the state of the relay, you are replacing its state. To emit both, you will need to concatenate the two arrays.
In general, you should avoid using Relays and Subjects in production code. They are good for learning the Rx system and samples but are hard to get right in real world situations. You only need them when converting non-Rx code into Rx or when setting up a feedback loop.
Also, a Subject, Relay or Observable shouldn't be a var. You don't want to replace one once setup. Make them lets instead.

Swift: Efficient solutions for nested for loops

I am looking for a more efficient solution for exhaustively comparing objects of the same array to each in Swift. Nesting for-in loops is exhaustive, simple, and returns correct results but the time complexity is O(n^2) which nobody recommends when it comes to performance and larger data sets. I hunted around for solutions for a long time, and only found people describing the for-in loop scenario as a classic example of quadratic time complexity. Help?
EDIT (now includes func tableView(tableView: cellForRowAt:) code ) :
Ok let’s go deeper as requested.
Think of a UITableView where you have an array of Event objects.
Event is a class, and you want to exhaustively check the array’s Event objects against each other for conflicts.
The array is already sorted chronologically by each Event element’s startTike property. There could be duplicate events because maybe a user would want that (who knows why, but that’s the end user’s choice to make).
Each Event object has a DateInterval property for this check.
If a conflict is found, you will need to run logic to evaluate the conflict.
If certain criteria are met, then you set a Boolean property (isConflicted) on the Event object.
The resulting array is then used to pass the indexPath.row specific Event object to a custom UITableViewCell for presentation in the UITableView where that ‘isConflicted’ Boolean is integral to the UITableViewCell’s layout/presentation.
Here is the nested for in loop solution I have working just fine, though the run time complexity is not great.
apologies for not including code earlier. i, mistakenly, didn't think it was necessary.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// unwrap my custom cell
guard let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as? EventDetailTableViewCell else {
return UITableViewCell()
}
// get the relevant section's events array from EventModelController.shared.groupedEventsDictionary check for nil
guard let events = EventModelController.shared.groupedEventsDictionary[sections[indexPath.section]] else {
print("ERROR: no event value found in EventModelController.shared.groupedEventsDictionary[sections[indexPath.section]] in EventsTableViewController.swift -> tableView(cellForRowAt:) - line 117.")
return UITableViewCell()
}
var eventDictionary: [DateInterval : Event] = [:]
for event in events {
eventDictionary[event.dateInterval] = event
}
// START: - option with time complexity O(n^2) that always works
// check the array for conflicts and set relevant event's isConflicted property
for event in events {
for anotherEvent in events {
// ensure that we don't redundantly check the same events against themselves
if event != anotherEvent {
if event.dateInterval.intersects(anotherEvent.dateInterval) {
if event.stopTime == anotherEvent.startTime || event.startTime == anotherEvent.stopTime {
event.isConflicted = false
} else {
event.isConflicted = true
}
}
}
}
}
// END: - option with time complexity O(n^2) that always works
// Configure the cell...
cell.event = events[indexPath.row]
return cell
}
There is a suggestion.
extension Array where Element: Hashable {
var containsDouplicated: Bool {
Set<Element>.init(self).count < self.count
}
}
I created this extension in order to use power of Sets to eliminate duplicated values, and after that I checked if the set (which has only unique values) has the same number of elements.
I think this is O(2n) so O(n).
There is an example of how to use it.
let a1 = [1,2,3]
let a2 = [1,2,3,4,1]
a1.containsDouplicated // false
a2.containsDouplicated // true
extension Array where Element: Hashable {
var containsDouplicated: Bool {
Set<Element>.init(self).count < self.count
}
}
EDIT: After your edit I suggest you to make Event : Hashable and implement a kind of:
extension Array where Element: Hashable {
var containsDouplicates: Bool {
Set<Element>.init(self).count < self.count
}
var orderedUniqueElements: [Element] {
var uniq: Set<Element> = .init(self)
let filtered: [Element] = self.filter { element -> Bool in
if !uniq.contains(element) {
return false
} else {
uniq.remove(element)
}
return true
}
return filtered
}
}
in order to preserve indexPath.

Use a function that needs UITableView in another view?

In my WalletTableViewController I have two functions, used to calculate the Wallet Value:
A. updateCellValue() Is called by reloadData() with the tableView and uses indexPath.row to fetch a value (price) and an amount (number of coins) corresponding to the cell and make a calculation to get the total value of that coin (amountValue = value * amount). That is then saved with Core Data.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! WalletTableViewCell
cell.delegate = self
cell.amountTextField.delegate = self
updateCellValue(cell, atRow: indexPath.row)
return cell
}
func updateCellValue(_ walletTableViewCell: WalletTableViewCell, atRow row: Int) {
var newCryptos : [CryptosMO] = []
var doubleAmount = 0.0
if CoreDataHandler.fetchObject() != nil {
newCryptos = CoreDataHandler.fetchObject()!
}
cryptoPrice = cryptos[row].code!
guard let cryptoDoublePrice = CryptoInfo.cryptoPriceDic[cryptoPrice] else { return }
let selectedAmount = newCryptos[row]
guard let amount = selectedAmount.amount else { return }
var currentAmountValue = selectedAmount.amountValue
doubleAmount = Double(amount)!
let calculation = cryptoDoublePrice * doubleAmount
currentAmountValue = String(calculation)
CoreDataHandler.editObject(editObject: selectedAmount, amount: amount, amountValue: currentAmountValue)
updateWalletValue()
}
B. updateWalletValue() Is a function that fetches all the amountValue objects in Core Data and adds them together to calculate the Wallet Value.
func updateWalletValue() {
var items : [CryptosMO] = []
if CoreDataHandler.fetchObject() != nil {
items = CoreDataHandler.fetchObject()!
}
total = items.reduce(0.0, { $0 + Double($1.amountValue)! } )
WalletTableViewController.staticTotal = total
}
In my MainViewController, the Wallet Value is displayed too, but how can I refresh it's value?
func updateMainVCWalletLabel() {
//... what can I do here??
}
This works great for the WalletViewController of course with the TableView and indexPath, but how can I call updateCellValue from the MainViewController to keep the value updated?
The WalletViewController is instantiated and pushed from the MainViewController :
#IBAction func walletButtonTapped(_ sender: Any) {
let walletViewController = self.storyboard?.instantiateViewController(withIdentifier: "walletTableViewController")
self.present(walletViewController!, animated: true)
}
If you want to use a single method in multiple view controllers you should implement that method where you can call that method from anywhere. For example you can use singleton class here.
Create a swift file and name it as your wish (like WalletHelper or WalletManager)
Then you will get a file with the following format
class WalletHelper: NSObject
{
}
Create a shared instance for that class
static let shared = WalletHelper()
Implement the method you want
func getWalletValue() -> Float {
// write your code to get wallet value`
// and return the calculated value
}
Finally call that method like
let walletValue = WalletHelper.shared. getWalletValue()
WalletHelper.swift looks like
import UIKit
class WalletHelper: NSObject
{
static let shared = WalletHelper()
func getWalletValue() -> Float {
// write your code to get wallet value
// and return the calculated value
}
}
Update (old answer below)
To me it is absolutly unclear what you want to achieve: Which value do you want to be updated? The staticTotal?
Seems a litte like an XYProblem to me. As #vadian commented yesterday, please clearly describe where the data is stored, how the controllers are connected, what you want to update when in order to achieve what. You could also provide a MCVE which makes clear what you are asking, instead of adding more and more code snippets.
And, even more interesting: Why do you modify CoreData entries (CoreDataHandler.editObject) when you are in the call stack of tableView(_: cellForRowAt:)? Never ever ever do so! You are in a reading case - reloadData is intended to update the table view to reflect the data changes after the data has been changed. It is not intended to update the data itself. tableView(_: cellForRowAt:) is called many many times, especially when the user scrolls up and down, so you are causing large write impacts (and therefore: performance losses) when you write into the database.
Old Post
You could just call reloadData on the table view, which then will update it's cells.
There are also a few issues with your code:
Why do you call updateWalletValue() that frequently? Every time a cell is being displayed, it will be called, run through the whole database and do some reduce work. You should cache the value and only update it if the data itself is modified
Why do you call fetchObject() twice (in updateWalletValue())?
You should do this:
func updateWalletValue() {
guard let items:[CryptosMO] = CoreDataHandler.fetchObject() else {
WalletTableViewController.staticTotal = 0.0
return
}
total = items.reduce(0.0, { $0 + Double($1.amountValue)! } )
WalletTableViewController.staticTotal = total
}

Need Help displaying Core Data in a UITableView in Swift

Please forgive if this is a duplicate question. I did search as thoroughly as I could, but none of the other questions that I've seen regarding core data in a UITableView seem to quite fit what I am trying to do.
Basically, I have two "tables" in my Core Data:
cstProjects and plProjects
Both tables have attributes called "propertyOwner" and "propertyID" (among others), that are set as Strings.
Next, in a ViewController, I have a table view instance, with the style set to Subtitle, and the cell identifier set to "projectCell".
Because I have two tables in my core data, I initialize the table to having two sections. I would like the first section to show all of the projects in the cstProjects table, and the second section to show all of the projects in the plProjects table.
Here is my ViewController code so far. I've put comments in, to explain it as best as I can. The functions that I have created might be a bit overkill to figure out how many "rows" each section should have, but I didn't know of a simpler way of going about it.
In the code below, where you see the double question marks "??" is where I am not sure what to put in order to show the current "row" of the type of project that we're currently iterating through.
Ultimately though, if I had to simplify my question down as much as possible, I just need to know how to show the rows of a core data table in a UITableView.
import UIKit
import CoreData
class LoadProjectViewController: UIViewController, UITableViewDataSource, NSFetchedResultsControllerDelegate {
let projectSectionCount: Int = 2
let cstSection: Int = 0
let plSection: Int = 1
// Implement UITableViewDataSource methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return projectSectionCount
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch(section) {
case cstSection:
return getCSTProjects()
case plSection:
return getPLProjects()
default:
return 0
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("projectCell")! as UITableViewCell
switch (indexPath.section) {
case cstSection:
//this is where I need to set the property owner for the CST Project
cell.textLabel!.text = ??
//this is where I need to set the project ID for the CST Project
cell.detailTextLabel!.text = ??
case plSection:
//this is where I need to set the property owner for the PL Project
cell.textLabel!.text = ??
//this is where I need to set the project ID for the PL Project
cell.detailTextLabel!.text = ??
default:
cell.textLabel!.text = "Unknown"
}
return cell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case cstSection:
return "Standing Timber Projects"
case plSection:
return "Purchased Logs"
default:
return "Unknown"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getCSTProjects() -> Int {
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context: NSManagedObjectContext = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "CSTProjects")
var results = [AnyObject]()
request.returnsObjectsAsFaults = false
do {
results = try context.executeFetchRequest(request)
} catch let error {
print("There was an error loading the data. \(error)")
}
if (results.count > 0) {
return results.count
} else {
return 0
}
}
func getPLProjects() -> Int {
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context: NSManagedObjectContext = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "PLProjects")
var results = [AnyObject]()
request.returnsObjectsAsFaults = false
do {
results = try context.executeFetchRequest(request)
} catch let error {
print("There was an error loading the data. \(error)")
}
if (results.count > 0) {
return results.count
} else {
return 0
}
}
}
The first thing you need to do in that method is look up which instance you want to display. To do that, you should modify your getCSTProjects and getPLProjects methods to save the results of the fetch request instead of throwing them away. You'd do that by adding new attributes to the view controllers to hold the arrays. On a related note, you really do not want to call those methods from tableView(tableView:, numberOfRowsInSection:), because that method can get called a lot. Doing fetches there pretty much guarantees poor performance.
To get a specific instance, look it up in one of the arrays you now have, using the indexPath argument to get the array index.
Once you have that specific instance, you need to look up values of the attributes you have declared on those Core Data entity types. What to put there depends on how your CSTProjects and PLProjects entities are defined and on whether you have created subclasses of NSManagedObject for them.
For example if your CSTProjects entity has a string attribute called name that you want to use as the title, and you do not have an NSManagedObject subclass, you could use this:
cell.textLabel!.text = currentInstance.value(forKey: "name") as? String
If you do have an NSManagedObject subclass (and it's always a good idea), this would be
cell.textLabel!.text = currentInstance.name
Rather than try to merge two entities (or tables) into a single fetchedResultsController, it would be easier to bring the data into a single table and access that.
If the tables are sufficiently similar, you could do this in a single table with a type code to differentiate the entries where you need to, for example using a filtered view to make the tables look like one type or the other in other parts of your code. This would mean making any fields limited to one type optional so the other could ignore them. Then the frc could use the code field as a section break.
Alternatively, if the tables are sufficiently different you could add a third table, say Projects, which had optional one-to-one links to the other two tables and drive the frc off of that third table using the links to populate fields in your tableView in the configure cell delegate method.
Besides making it easier to build the current frc structure, either of these approaches would make adding a third or fourth type much easier if your requirements expand in the future, and would avoid the complications that inevitably follow from bending an API to fit a use it wasn't designed for.

Realm date-query

In my RealmSwift (0.92.3) under Xcode6.3, how would I
// the Realm Object Definition
import RealmSwift
class NameEntry: Object {
dynamic var player = ""
dynamic var gameCompleted = false
dynamic var nrOfFinishedGames = 0
dynamic var date = NSDate()
}
The current tableView finds the number of objects (i.e. currently all objects) like follows:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let cnt = RLM_array?.objects(NameEntry).count {
return Int(cnt)
}
else {
return 0
}
}
First question: How would I find the number of objects that have a date-entry after, let's say, the date of 15.06.2014 ?? (i.e. date-query above a particular date from a RealmSwift-Object - how does that work ?). Or in other words, how would the above method find the number of objects with the needed date-range ??
The successful filling of all Realm-Objects into a tableView looks as follows:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("NameCell") as! PlayersCustomTableViewCell
if let arry = RLM_array {
let entry = arry.objects(NameEntry)[indexPath.row] as NameEntry
cell.playerLabel.text = entry.player
cell.accessoryType = entry.gameCompleted ? .None : .None
return cell
}
else {
cell.textLabel!.text = ""
cell.accessoryType = .None
return cell
}
}
Second question: How would I fill into the tableView only the RealmSwift-Objects that have a particular date (i.e. for example filling only the objects that have again the date above 15.06.2014). Or in other words, how would the above method only fill into the tableView the objects with the needed date-range ??
You can query Realm with dates.
If you want to get objects after a date, use greater-than (>), for dates before, use less-than (<).
Using a predicate with a specific NSDate object will do what you want:
let realm = Realm()
let predicate = NSPredicate(format: "date > %#", specificNSDate)
let results = realm.objects(NameEntry).filter(predicate)
Question 1: For the number of objects, just call count: results.count
Question 2: results is an array of NameEntrys after specificNSDate, get the object at indexPath. Example, let nameEntry = results[indexPath.row]
For creating a specific NSDate object, try this answer: How do I create an NSDate for a specific date?

Resources