How to return multiple rows or table for SqLite in swift? - ios

I am using SqLite library for swift. I can return one row with this method,
func getById(id:Int64) -> Row?{
do{
let query=Users.filter(Id==id)
print(query.asSQL())
var data = try db!.pluck(query)
return data
}catch{
print("Error: \(error)")
return nil
}
}
This function is returning "Row" it's ok. But i am using tableView object so i need one dataSource.
How can i return table and set datasource for tableView, i have not found an example of this.
Best regards.

You can use this code:
I don't know all of your classes, but this is the main method to get query for SQLite3(swift), go through all results(if multiple), append them and return the whole data at the end.
//You say you want to return array of rows
func getById(id:Int64) -> [Row]? {
//Create empty array
var data = [Row]()
//build the query. I use UsersTable.entityName.filter(), but I don't know your structure
let query=Users.filter(Id==id)
do {
//for cycle to go to all of the results
for rowInfo in try db!.pluck(query) {
//Create variable. I don't know what you want. You can create it as Row() and after that add the information
let userData = Row()
//you need to use rowInfo, it store the SQL data. inside the key is from the table Structure. You used Users.filter, so I guess the struct with all column names is Users, so Users.name is the 'name' column
userData.name = rowInfo[Users.name]
//Apend the data
data.append(userData)
}
} catch {
return nil
}
//Return the array of Rows
return data
}

Related

iOS: Cast result of coredata fetch to array and passing to another class

in my class I have a method to extract data from coredata. But I have a problem: I need to convert the result to an array, because then I'll have to use that array in an other class.
The method is:
func loadQuestion() -> NSArray{
let fetchRequest: NSFetchRequest<Questions> = Questions.fetchRequest()
do {
let array = try self.context.fetch(fetchRequest) as NSArray
guard array.count > 0 else { print("[EHY!] Non ci sono elementi da leggere "); return array }
return array
} catch let errore {
print("error FetchRequest")
}
return list
}
I can't figure out how to convert the variable array?
The result (wrong)
Edit: I write this because I want to convert the result of fetch into
an array, so you can switch to another class
fetch returns an (optional) array, so all you need to do is return that from your function. Since fetch throws your function should either throw or at least return an optional, as the fetch can fail.
In Swift it is very rarely necessary to use NSArray; a properly typed Swift array will make your code clearer and safer. Since CoreData in Swift supports Generics, fetch will return the appropriate array type automatically, based on your NSFetchRequest. Even if you are calling this function from Objective-C, it is best to let the compiler bridge the Swift array to an NSArray for you
Finally, you are using guard incorrectly; you attempt to return array in the case where it has 0 items, otherwise you return some variable list which isn't declared in the code you have shown.
func loadQuestion() -> [Questions]? {
let fetchRequest: NSFetchRequest<Questions> = Questions.fetchRequest()
do {
let array = try self.context.fetch(fetchRequest) as [Questions]
return array
} catch let errore {
print("error FetchRequest \(errore)")
}
return nil
}

Couchbase Lite View Aggregation Values are null (empty)

I'm trying to do a simple view, that takes my data and groups all of my records by a key "sortDate". I feel like i've followed all the examples, read all the documents multiple times and it just doesn't work as expected.
Here is the view code i'm creating:
guard let database = database else { return }
database.viewNamed("byDate").setMapBlock({ (doc, emit) in
if let date = doc["sortDate"] as? String {
emit(date, doc)
}
}, version: "8")
let query = database.viewNamed("byDate").createQuery()
query.groupLevel = 1
query.descending = true
do {
let result = try query.run()
print(result)
while let row = result.nextRow() {
print(row)
print(row.value) //EMPTY
}
} catch {
print("Failed to retrieve all documents for \(database.name) database")
}
My row.value is NULL even though there are multiple records in the database, my allDocs query is returning just fine.
Specifying a grouplevel when the key is not an array causes CBL to aggregate the results using the reduce function. You haven't specified one, so that's why you get no results.
From the docs:
The value property of each row will be the result of running the view's reduce function over all the rows that were aggregated; or if the view has no reduce function, there's no value. (See the View documentation for information on reduce functions.)

How to check if 2 arrays have the same element and if it does, delete that element from one of the arrays?

I currently have 2 arrays, one called rewardsArray and one called expiredRewardsArray. The rewardsArray I'm getting from an api thats fetched every time I connect. The expiredRewardsArray I save locally. What I'm trying to do is in the viewDidLoad, after I retrieve the rewardsArray data I want to compare it to the expiredRewardsArray's data. If there is a match I want to remove the item from the rewardsArray. This is what I have so far but it never goes inside the "if let" brackets so it's not removing the item from the rewardsArray:
func rewardsMinusExpired () {
expiredRewardsArray = rewardManager.getExpiredRewards()
for expiredReward in expiredRewardsArray {
if let ex = rewardsArray.indexOf(expiredReward){
print("Expired Reward to be removed: \(ex)")
rewardsArray.removeAtIndex(ex)
rewardsTableView.reloadData()
}
}
}
Each item in the array has an id, I use that to see if the item is in the expiredRewardsArray:
for expiredReward in expiredRewardsArray {
print("This is an expired reward: \(expiredReward.id)")
}
Here's a solution that uses Set arithmetic. As a consequence, it's really fast, but it will not preserve the ordering of elements, and it will clobber any duplicates. It runs in linear time (O(n)), whereas a naive approach would be O(n^2).
let unexpiredRewards = Set(rewardsArray).subtract(Set(ExpiredRewards))
for item in expiredRewardsArray {
if let index = rewardsArray.index(of: item) {
//found the item
rewardsArray.remove(at: index)
}
}
This will find the item and delete it from the rewardsArray
UPDATE:
You say that each item has an id. If with the code above the if let block is never called than you can be sure that the items aren't actually the same or you don't have any equal items.
for itemOne in expiredRewardsArray {
for itemTwo in rewardsArray {
if itemOne.id == itemTwo.id {
rewardsArray.remove(at: index)
}
}
}
Not very performant but it does its job and keeps the order
You should really use swift method filter in cases like this. This can be easily solved as this,
func rewardMinusExpired() {
let notExpiredRewards = rewardsArray.filter { a in
return !expiredRewardArray.contains(a)
}
}
If expiredRewardsArray and rewardsArray are arrays of objects, then you'll need to compare the elements using their id property to compare them, rather than indexOf(_:). The reason for this is that objects are reference types, so you can have two different objects with identical properties, but if they're not the same object, indexOf(_:) will treat them as separate entities.
Try this code instead:
func rewardsMinusExpired() {
expiredRewardsArray = rewardManager.getExpiredRewards()
rewardsArray = rewardsArray.filter { reward in
let isExpired = expiredRewardsArray.contains { expiredReward in
return expiredReward.id == reward.id
}
return !isExpired
}
}

Access Parse Array Elements

I have an array column in Parse that is called homeAddress. Inside it is the following value for a single row:
["111111","222222"]
I wish to access this in swift. I created a local array called homeAddress of String type. How can I store the first element in the Parse column (i.e. 111111) in the first element holder in local array i.e. homeAddress[0]? And then I need to store the 222222 in the homeAddress[1].
So what you want is load this data from parse. You can just call a Parse Query get the results and work with them:
let query = PFQuery(className:"ClassName")
query.findObjectsInBackgroundWithBlock {
(results, error) -> Void in
if (error == nil) {
for object in results!{
let homeAddress = object["homeAddress"] as! NSArray
}
}else {
print(error?.userInfo)
}
}
One way would be to trim first and last character and just separate values by comma:
var test = "[\("111111"),\("222222")]"
var trimmedStringRange = Range<String.Index>(start: test.startIndex.successor(), end: test.endIndex.predecessor())
var homeAddress = test.substringWithRange(trimmedStringRange).componentsSeparatedByString(",")
If your local array is empty, you can add your values from the parse array like this (after getting the array from Parse):
localHomeAddress.append(homeAddress)
This will put all values from homeAddress array in localHomeAddress array.
If you use a splice, you can ensure you are adding the values from index 0:
localHomeAddress.insertContentsOf(homeAddress, at:0)

How to delete a specific row in the table using Swift CoreData

I new to Swift programming. I am using CoreData in my app as a database option.
I am using NSManagedObject (deleteObject) to delete lastObject, firstObject and entire rows in the table.
I want to delete a specific row in the table by using a value which is stored in a variable. I am not using table view (I don't have any index path), this delete operation is the background process after I get response from the my application server.
Any links or tutorials or suggestions will be helpful.
Thanks in advance!!!
Code for deleting lastObject
if var results1 = context.executeFetchRequest(requestParams, error: nil) as? [Params] {
println("\n Params Results count : \(results1.count)")
for param in results1{
for var n = 0 ;n < results1.count; ++n
{
let lastPerson = (results1 as NSArray).lastObject as Params
context.deleteObject(lastPerson)
var savingError: NSError?
context.save(&savingError)
}
}
}
Params table consists of columns 'pname' and 'pvalues'.
I want to delete a specific param pname ='server_timeout'.
Consider if 'Params' table consist of 10 rows and 'pname'='server_timeout' might be present at index 5, 6.
How can I find the 'pname' (i.e 'server_timeout') in this list of records and delete it?
How about creating a predicate that filters out the list to those with pname value of server_timeout in the first place.
context.performBlock {
requestParams.predicate = NSPredicate(format: "pname == %#", "server_timeout")
if let results = context.executeFetchRequest(requestParams, error: nil) as? [Params] {
for param in results {
context.deleteObject(param)
}
var error: NSError?
if !context.save(&error) {
println(error)
}
}
}
As you can see, I have placed the whole search-and-delete inside a performBlock closure. I don't know how you have setup your Core Data, but you might want to consider threading to maximize perceived performance.

Resources