Swift concatenate string based on different values - ios

I need to concatenate a string based on some logic but I cant figure out how to do it.
Example:
var filterString: String = ""
var hasFilter: Bool = false
if let catId = param["catid"] {
filterString += "cat_id=\(catId)"
hasFilter = true
}
if let subCatId = param["subcatid"] {
filterString += "sub_cat_id=\(subCatId)"
hasFilter = true
}
if let locationId = param["stateid"] {
filterString += "location_id=\(locationId)"
hasFilter = true
}
if hasFilter == true {
query.filters = filterString
}
This will only work if I have ONE filter in my query
Eg: query.filters = "location_id=4"
But if I happend to have two or more filters my query will break eg:
query.filters = "location_id=4cat_id=3"
If I have more then one filter I need to seperate it with a AND statement like this:
query.filters = "location_id=4 AND cat_id=3"
But I cant figure out how to do it since I never know what order the filter will come in or if there even will be one or more filters to begin with
Edit
I seem to get it working by:
var filterString: String = ""
var hasFilter: Bool = false
if let catId = param["catid"] {
filterString += "cat_id=\(catId)"
hasFilter = true
}
if let subCatId = param["subcatid"] {
if hasFilter == true {
filterString += " AND sub_cat_id=\(subCatId)"
} else {
filterString += "sub_cat_id=\(subCatId)"
}
hasFilter = true
}
if let locationId = param["stateid"] {
if hasFilter == true {
filterString += " AND location_id=\(locationId)"
} else {
filterString += "location_id=\(locationId)"
}
hasFilter = true
}
if hasFilter == true {
query.filters = filterString
}

One solution would be to put the filters into an array and then if the array isn't empty, combine the array values with an " AND " separator.
var filters : [String] = []
if let catId = param["catid"] {
filters.append("cat_id=\(catId)")
}
if let subCatId = param["subcatid"] {
filters.append("sub_cat_id=\(subCatId)")
}
if let locationId = param["stateid"] {
filters.append("location_id=\(locationId)")
}
if filters.count > 0 {
query.filters = filters.joined(separator: " AND ")
}

Maybe you can first create an array and append all the filters.
After that create another variable to append all the values in the array.

Another option using inline if statements:
var param = ["catid" : "111", "subcatid" : "222", "stateid" : "333"]
var filterString = ""
if let catId = param["catid"] {
filterString = "cat_id=\(catId)"
}
if let subCatId = param["subcatid"] {
filterString.appendContentsOf(filterString.characters.count > 0 ? " AND sub_cat_id=\(subCatId)" : "sub_cat_id=\(subCatId)")
}
if let locationId = param["stateid"] {
filterString.appendContentsOf(filterString.characters.count > 0 ? " AND location_id=\(locationId)" : "location_id=\(locationId)")
}
print(filterString)
if (filterString.characters.count > 0) {
query.filters = filterString
}

Related

What is the replacement for AKSampler.loadMelodicSoundFont in AudioKit 4.2?

I had to upgrade from AudioKit 4.0 to AudioKit 4.2 due to an incompatibility of AudioKit 4.0 with latest swift language and Xcode.
However, now my project cannot be compiled because loadMelodicSoundFont is not a member of AKSampler anymore while I'm using this method to load sf2 sound file.
I could find a documentation for 4.1 only on http://audiokit.io/docs/ and 4.1 has loadMelodicSoundFont apparently. And no documentation for 4.2 I could find.
So what is the replacement for this method in AudioKit 4.2?
The new AKSampler class in the latest versions of AudioKit is an entirely new custom sampler. However, as of right now it no longer handles SoundFont files natively (that's what your sf2 file is).
The easiest way for you would simply be to switch to AKAppleSampler, which is the fully featured sampler from previous versions of AudioKit. It relies on the Apple AU code and is still able to load SoundFont files.
So in practice you would simply rename your references to AKSampler to AKAppleSampler in your code.
You can rewrite the loadBetterSFZ sampler-extension function in the AKsampler example. This only reads for the included converted files and presumes the sample file is the last part of a region.
I did so and now I can use to sfz converted sf2 files from polyphony(windows) and sforzando and read the file for as far as I understand AKSampler can hold. I made a class to read the sfz file into a data structure that holds the data for reuse. For the sampler I wrote an extension that loads from the created data. Its all quick and dirty (I am not a programmer!). There are many different ways sfz files seem to be structured and I only tried a dozen or so.
example: add class SFZData to conductor in the example
get data with func SFZData.parseSFZ(folderPath: String, sfzFileName: String)->SFZ?
use SFZ for the extension in sampler: func loadSFZData(sfz:SFZ)
//here is what I did(all last versions and works on iPhone 6s)
import Foundation
class regionData {
var lovel: Int32 = -1 //not set, use group
var hivel: Int32 = -1
var lokey: Int32 = -1
var hikey: Int32 = -1
var pitch: Int32 = -1
var tune: Int32 = 0
var transpose: Int32 = 0
var loopmode: String = ""
var loopstart: Float32 = 0
var loopend: Float32 = 0
var startPoint: Float32 = 0
var endPoint: Float32 = 0
var sample: String = ""
init(){
}
}
class groupData {
var lovel: Int32 = 0
var hivel: Int32 = 127
var lokey: Int32 = 0
var hikey: Int32 = 127
var pitch: Int32 = 60
var loopmode: String = ""
var sample: String = ""
var regions = [regionData]()
init(){
}
}
class globalData {
var samplePath = ""
var lovel: Int32 = 0
var hivel: Int32 = 127
var sample: String = ""
var groups = [groupData]()
//ampdata?
//filterdata?
init(){
}
}
class ampData {
// in global and or group?
}
class SFZ {
var sfzName = ""
var baseURL : URL!
var global = globalData()
var group = [groupData?]()
init(){
//
}
}
class SFZdata {
var sfzChuncks = [String:SFZ]()
init(){
}
func getData(folderPath: String, sfzFileName: String)->SFZ?{
let sfzdata = sfzChuncks[sfzFileName]
if sfzdata != nil {
return sfzdata
}
return parseSFZ(folderPath:folderPath,sfzFileName:sfzFileName)
}
func parseSFZ(folderPath: String, sfzFileName: String)->SFZ? {
//let globalName = "<global>"
//let groupName = "<group>"
let regionName = "<region>"
var filePosition : String.Index
var chunck = ""
var data: String
let sfz = SFZ()
//stopAllVoices()
//unloadAllSamples()
let baseURL = URL(fileURLWithPath: folderPath)
let sfzURL = baseURL.appendingPathComponent(sfzFileName)
do {
data = try String(contentsOf: sfzURL, encoding: .ascii)
}catch {
debugPrint("file not found")
return nil
}
sfz.sfzName = sfzFileName
filePosition = data.startIndex
while filePosition != data.endIndex {
chunck = findHeader(data: data,dataPointer: &filePosition)
switch chunck {
case "<global>":
//get end of gobal and read data
let globaldata = readChunck(data: data, dataPointer: &filePosition)
let trimmed = String(globaldata.trimmingCharacters(in: .whitespacesAndNewlines))
sfz.global = readGlobal(globalChunck: trimmed)!
break
case "<group>":
//get end of group and read data
//first read this one the
let groupdata = readChunck(data: data, dataPointer: &filePosition)
let trimmed = String(groupdata.trimmingCharacters(in: .whitespacesAndNewlines))
let mygroup = readGroup(groupChunck: trimmed)
chunck = findHeader(data: data, dataPointer: &filePosition)
while chunck == regionName {
//read region and append
let regiondata = readChunck(data: data, dataPointer: &filePosition)
let trimmed = String(regiondata.trimmingCharacters(in: .whitespacesAndNewlines))
let myRegion = readRegion(regionChunck: trimmed)
mygroup?.regions.append(myRegion)
chunck = findHeader(data: data, dataPointer: &filePosition)
}
if chunck != regionName && filePosition != data.endIndex {
//back to before header if ! endoffile
filePosition = data.index(filePosition, offsetBy: -(chunck.count))
}
sfz.group.append(mygroup)
break
// case region without group ? ignore
default:
//ignore
break
}
}
sfz.baseURL = URL(fileURLWithPath: folderPath)
sfzChuncks.updateValue(sfz, forKey: sfzFileName)
return sfz
}
func findHeader(data:String, dataPointer:inout String.Index)->(String) {
if dataPointer == data.endIndex {
return ("")
}
while dataPointer != data.endIndex {
if data[dataPointer] == "<" { break }
dataPointer = data.index(after: dataPointer)
}
if dataPointer == data.endIndex {
return ("")
}
let start = dataPointer
while dataPointer != data.endIndex {
if data[dataPointer] == ">" { break }
dataPointer = data.index(after: dataPointer)
}
dataPointer = data.index(after: dataPointer)
if dataPointer == data.endIndex {
return ("")
}
return (String(data[start..<dataPointer]))
}
func readChunck(data:String,dataPointer:inout String.Index)->String{
var readData = ""
if dataPointer == data.endIndex { return readData }
while dataPointer != data.endIndex {
if data[dataPointer] == "<" {
break
} else {
readData.append(data[dataPointer])
dataPointer = data.index(after: dataPointer)
}
}
if dataPointer == data.endIndex {return readData }
if data[dataPointer] == "<" {
dataPointer = data.index(before: dataPointer)
}
return readData
}
func readGlobal(globalChunck:String)->globalData?{
let globaldata = globalData()
var samplestring = ""
var global = globalChunck
for part in globalChunck.components(separatedBy: .newlines){
if part.hasPrefix("sample") {
samplestring = part
}
}
if samplestring == "" {
//check for structure
if global.contains("sample") {
//get it out
var pointer = global.startIndex
var offset = global.index(pointer, offsetBy: 6, limitedBy: global.endIndex)
var s = ""
while offset != global.endIndex {
s = String(global[pointer..<offset!])
if s.contains("sample") {break}
pointer = global.index(after: pointer)
offset = global.index(pointer, offsetBy: 6, limitedBy: global.endIndex)
}
if s.contains("sample") {
//read to end
samplestring = String(global[pointer..<global.endIndex])
}
}
}
if samplestring != "" {
globaldata.sample = samplestring.components(separatedBy: "sample=")[1].replacingOccurrences(of: "\\", with: "/")
global = global.replacingOccurrences(of: samplestring, with: "", options: NSString.CompareOptions.literal, range: nil)
}
for part in global.components(separatedBy: .newlines) {
if part.hasPrefix("lovel") {
globaldata.lovel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("hivel") {
globaldata.hivel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("sample") {
globaldata.sample = part.components(separatedBy: "sample=")[1].replacingOccurrences(of: "\\", with: "/")
}
}
return globaldata
}
func readGroup(groupChunck:String)->groupData?{
let groupdata = groupData()
var samplestring = ""
var group = groupChunck
for part in groupChunck.components(separatedBy: .newlines){
if part.hasPrefix("sample") {
samplestring = part
}
}
if samplestring == "" {
//check for structure
if group.contains("sample") {
//get it out
var pointer = group.startIndex
var offset = group.index(pointer, offsetBy: 6, limitedBy: group.endIndex)
var s = ""
while offset != group.endIndex {
s = String(group[pointer..<offset!])
if s.contains("sample") {break}
pointer = group.index(after: pointer)
offset = group.index(pointer, offsetBy: 6, limitedBy: group.endIndex)
}
if s.contains("sample") {
//read to end
samplestring = String(group[pointer..<group.endIndex])
}
}
}
if samplestring != "" {
groupdata.sample = samplestring.components(separatedBy: "sample=")[1].replacingOccurrences(of: "\\", with: "/")
group = group.replacingOccurrences(of: samplestring, with: "", options: NSString.CompareOptions.literal, range: nil)
}
for part in group.components(separatedBy: .whitespacesAndNewlines) {
if part.hasPrefix("lovel") {
groupdata.lovel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("hivel") {
groupdata.hivel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("lokey") {
groupdata.lokey = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("hikey") {
groupdata.hikey = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("pitch_keycenter") {
groupdata.pitch = Int32(part.components(separatedBy: "=")[1])!
}else if part.hasPrefix("loop_mode") {
groupdata.loopmode = part.components(separatedBy: "=")[1]
}
}
return groupdata
}
func readRegion(regionChunck:String)->regionData{
let regiondata = regionData()
var samplestring = ""
var region = regionChunck
for part in regionChunck.components(separatedBy: .newlines){
if part.hasPrefix("sample") {
samplestring = part
}
}
// this for formats in wich ther are no newlines between region elements
if samplestring == "" {
//check for structure
if region.contains("sample") {
//get it out
var pointer = region.startIndex
var offset = region.index(pointer, offsetBy: 6, limitedBy: region.endIndex)
var s = ""
while offset != region.endIndex {
s = String(region[pointer..<offset!])
if s.contains("sample") {break}
pointer = region.index(after: pointer)
offset = region.index(pointer, offsetBy: 6, limitedBy: region.endIndex)
}
if s.contains("sample") {
//read to end
samplestring = String(region[pointer..<region.endIndex])
}
}
}
if samplestring != "" {
regiondata.sample = samplestring.components(separatedBy: "sample=")[1].replacingOccurrences(of: "\\", with: "/")
region = region.replacingOccurrences(of: samplestring, with: "", options: NSString.CompareOptions.literal, range: nil)
}
for part in region.components(separatedBy: .whitespacesAndNewlines) {
if part.hasPrefix("lovel") {
regiondata.lovel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("hivel") {
regiondata.hivel = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("key=") {
regiondata.pitch = Int32(part.components(separatedBy: "=")[1])!
regiondata.lokey = regiondata.pitch
regiondata.hikey = regiondata.pitch
}else if part.hasPrefix("transpose") {
regiondata.transpose = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("tune") {
regiondata.tune = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("lokey") { // sometimes on one line
regiondata.lokey = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("hikey") {
regiondata.hikey = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("pitch_keycenter") {
regiondata.pitch = Int32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("loop_mode") {
regiondata.loopmode = part.components(separatedBy: "=")[1]
} else if part.hasPrefix("loop_start") {
regiondata.loopstart = Float32(part.components(separatedBy: "=")[1])!
} else if part.hasPrefix("loop_end") {
regiondata.loopend = Float32(part.components(separatedBy: "=")[1])!
}else if part.hasPrefix("offset") {
regiondata.startPoint = Float32(part.components(separatedBy: "=")[1])!
}
else if part.hasPrefix("end") {
regiondata.endPoint = Float32(part.components(separatedBy: "=")[1])!
}
}
return regiondata
}
}
extension for sampler:
func loadSFZData(sfz:SFZ){
stopAllVoices()
unloadAllSamples()
for group in sfz.group {
for region in (group?.regions)! {
var sd = AKSampleDescriptor()
if region.pitch >= 0 {
sd.noteNumber = region.pitch
} else {
sd.noteNumber = (group?.pitch)!
}
var diff = Float(1)
if region.tune != 0 {
let fact = Float(pow(1.000578,Double(region.tune.magnitude)))
if region.tune < 0 {
diff *= fact
} else {
diff /= fact
}
}
sd.noteFrequency = Float(AKPolyphonicNode.tuningTable.frequency(forNoteNumber: MIDINoteNumber(sd.noteNumber-region.transpose)))*diff
if region.lovel >= 0 {
sd.minimumVelocity = region.lovel
} else {
sd.minimumVelocity = (group?.lovel)!
}
if region.hivel >= 0 {
sd.maximumVelocity = region.hivel
} else {
sd.maximumVelocity = (group?.hivel)!
}
if region.lokey >= 0 {
sd.minimumNoteNumber = region.lokey
} else {
sd.minimumNoteNumber = (group?.lokey)!
}
if region.hikey >= 0{
sd.maximumNoteNumber = region.hikey
} else {
sd.maximumNoteNumber = (group?.hikey)!
}
sd.loopStartPoint = region.loopstart
sd.loopEndPoint = region.loopend
var loopMode = ""
if region.loopmode != "" {
loopMode = region.loopmode
} else if group?.loopmode != "" {
loopMode = (group?.loopmode)!
}
sd.isLooping = loopMode != "" && loopMode != "no_loop"
sd.startPoint = region.startPoint
sd.endPoint = region.endPoint
// build sampldescriptor from region
// now sample
var sample = region.sample
if sample == "" { sample = (group?.sample)! }
if sample == "" { sample = sfz.global.sample}
if sample != "" {
let sampleFileURL = sfz.baseURL.appendingPathComponent(sample)
if sample.hasSuffix(".wv") {
loadCompressedSampleFile(from: AKSampleFileDescriptor(sampleDescriptor: sd, path: sampleFileURL.path))
} else {
if sample.hasSuffix(".aif") || sample.hasSuffix(".wav") {
let compressedFileURL = sfz.baseURL.appendingPathComponent(String(sample.dropLast(4) + ".wv"))
let fileMgr = FileManager.default
if fileMgr.fileExists(atPath: compressedFileURL.path) {
loadCompressedSampleFile(from: AKSampleFileDescriptor(sampleDescriptor: sd, path: compressedFileURL.path))
} else {
do {
let sampleFile = try AKAudioFile(forReading: sampleFileURL)
loadAKAudioFile(from: sd, file: sampleFile)
} catch {
debugPrint("error loading audiofile")
}
}
}
}
} //if sample
} //region
} //group
buildKeyMap()
restartVoices()
}

SQLite db file is only read at the startup of the app

I have an issue with my code that I hope maybe som of you can help me out with.
I have a "kindoff" dictionary app where the user can search for abbreviations.
The datamodel is build using an SQLite database. In my first version the data.db file was only stored locally, but since I have to make a lot of data updates I don't wanna update en whole app every time. So I have made a version that gets the data.db file from a server instead.
My problem is that the user have to quit og restart the app to get the updated version. Somehow, even if the new file is copied to the directory the sqldb class does'nt read the new file. Any idea how to make som code the gets the dbclass to read the new file, while the app is running?
Here is the code the copies the new file to the directory
func executeDownloadTask(){
if Reachability.isConnectedToNetwork() == true{
print("just Checking")
let backgroundSessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("backgroundSession")
backgroundSession = NSURLSession(configuration: backgroundSessionConfiguration, delegate: self,delegateQueue: NSOperationQueue.mainQueue())
let the_path:String = UpdateDbFile.findPathInDocDir("data.db");// get the path for the data.db file
UpdateDbFile.deleteFilewithPath(the_path) // delete the existing file
startDownload() // download the updated dbfile
}
}
Heres the SQLiteDb class that I use.
//
// SQLiteDB.swift
// TasksGalore
//
// Created by Fahim Farook on 12/6/14.
// Copyright (c) 2014 RookSoft Pte. Ltd. All rights reserved.
//
import Foundation
#if os(iOS)
import UIKit
#else
import AppKit
#endif
let SQLITE_DATE = SQLITE_NULL + 1
internal let SQLITE_STATIC = unsafeBitCast(0, sqlite3_destructor_type.self)
internal let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)
// MARK:- SQLColumn Class - Column Definition
class SQLColumn {
var value:AnyObject? = nil
var type:CInt = -1
init(value:AnyObject, type:CInt) {
// println("SQLiteDB - Initialize column with type: \(type), value: \(value)")
self.value = value
self.type = type
}
// New conversion functions
func asString()->String {
switch (type) {
case SQLITE_INTEGER, SQLITE_FLOAT:
return "\(value!)"
case SQLITE_TEXT:
return value as! String
case SQLITE_BLOB:
if let str = NSString(data:value as! NSData, encoding:NSUTF8StringEncoding) {
return str as String
} else {
return ""
}
case SQLITE_NULL:
return ""
case SQLITE_DATE:
let fmt = NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
return fmt.stringFromDate(value as! NSDate)
default:
return ""
}
}
func asInt()->Int {
switch (type) {
case SQLITE_INTEGER, SQLITE_FLOAT:
return value as! Int
case SQLITE_TEXT:
let str = value as! NSString
return str.integerValue
case SQLITE_BLOB:
if let str = NSString(data:value as! NSData, encoding:NSUTF8StringEncoding) {
return str.integerValue
} else {
return 0
}
case SQLITE_NULL:
return 0
case SQLITE_DATE:
return Int((value as! NSDate).timeIntervalSince1970)
default:
return 0
}
}
func asDouble()->Double {
switch (type) {
case SQLITE_INTEGER, SQLITE_FLOAT:
return value as! Double
case SQLITE_TEXT:
let str = value as! NSString
return str.doubleValue
case SQLITE_BLOB:
if let str = NSString(data:value as! NSData, encoding:NSUTF8StringEncoding) {
return str.doubleValue
} else {
return 0.0
}
case SQLITE_NULL:
return 0.0
case SQLITE_DATE:
return (value as! NSDate).timeIntervalSince1970
default:
return 0.0
}
}
func asData()->NSData? {
switch (type) {
case SQLITE_INTEGER, SQLITE_FLOAT:
let str = "\(value)" as NSString
return str.dataUsingEncoding(NSUTF8StringEncoding)
case SQLITE_TEXT:
let str = value as! NSString
return str.dataUsingEncoding(NSUTF8StringEncoding)
case SQLITE_BLOB:
return value as? NSData
case SQLITE_NULL:
return nil
case SQLITE_DATE:
let fmt = NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
let str = fmt.stringFromDate(value as! NSDate)
return str.dataUsingEncoding(NSUTF8StringEncoding)
default:
return nil
}
}
func asDate()->NSDate? {
switch (type) {
case SQLITE_INTEGER, SQLITE_FLOAT:
let tm = value as! Double
return NSDate(timeIntervalSince1970:tm)
case SQLITE_TEXT:
let fmt = NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
return fmt.dateFromString(value as! String)
case SQLITE_BLOB:
if let str = NSString(data:value as! NSData, encoding:NSUTF8StringEncoding) {
let fmt = NSDateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
return fmt.dateFromString(str as String)
} else {
return nil
}
case SQLITE_NULL:
return nil
case SQLITE_DATE:
return value as? NSDate
default:
return nil
}
}
func description()->String {
return "Type: \(type), Value: \(value)"
}
}
// MARK:- SQLRow Class - Row Definition
class SQLRow {
var data = Dictionary<String, SQLColumn>()
subscript(key: String) -> SQLColumn? {
get {
return data[key]
}
set(newVal) {
data[key] = newVal
}
}
func description()->String {
return data.description
}
}
// MARK:- SQLiteDB Class - Does all the work
class SQLiteDB{
let DB_NAME = "data.db"
let QUEUE_LABLE = "SQLiteDB"
private var db:COpaquePointer = nil
private var queue:dispatch_queue_t
private var fmt = NSDateFormatter()
private var GROUP = ""
var newFileName = " "
var recentFileName = "Bøsse "
struct Static {
static var instance:SQLiteDB? = nil
static var token:dispatch_once_t = 0
}
class func sharedInstance() -> SQLiteDB! {
dispatch_once(&Static.token) {
Static.instance = self.init(gid:"")
}
return Static.instance!
}
class func sharedInstance(gid:String) -> SQLiteDB! {
dispatch_once(&Static.token) {
Static.instance = self.init(gid:gid)
}
return Static.instance!
}
required init(gid:String) {
assert(Static.instance == nil, "Singleton already initialized!")
GROUP = gid
// Set queue
queue = dispatch_queue_create(QUEUE_LABLE, nil)
// Set up for file operations
let fm = NSFileManager.defaultManager()
let dbName:String = String.fromCString(DB_NAME)!
var docDir = ""
// Is this for an app group?
if GROUP.isEmpty {
// Get path to DB in Documents directory
docDir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)[0] as String
} else {
// Get path to shared group folder
if let url = fm.containerURLForSecurityApplicationGroupIdentifier(GROUP) {
docDir = url.path!
} else {
assert(false, "Error getting container URL for group: \(GROUP)")
}
}
let path = docDir.NS.stringByAppendingPathComponent(dbName)
print(path)
// Check if copy of DB is there in Documents directory
if !(fm.fileExistsAtPath(path)) {
// The database does not exist, so copy to Documents directory
if let from = NSBundle.mainBundle().resourcePath?.NS.stringByAppendingPathComponent(dbName) {
var error:NSError?
do {
try fm.copyItemAtPath(from, toPath: path)
print("restart the app to get updated data")
} catch let error1 as NSError {
error = error1
print("SQLiteDB - failed to copy writable version of DB!")
print("Error - \(error!.localizedDescription)")
return
}
}
}
// Open the DB
let cpath = path.cStringUsingEncoding(NSUTF8StringEncoding)
let error = sqlite3_open(cpath!, &db)
if error != SQLITE_OK {
// Open failed, close DB and fail
print("SQLiteDB - failed to open DB!")
sqlite3_close(db)
}
fmt.dateFormat = "YYYY-MM-dd HH:mm:ss"
}
deinit {
closeDatabase()
}
private func closeDatabase() {
if db != nil {
// Get launch count value
let ud = NSUserDefaults.standardUserDefaults()
var launchCount = ud.integerForKey("LaunchCount")
launchCount--
print("SQLiteDB - Launch count \(launchCount)")
var clean = false
if launchCount < 0 {
clean = true
launchCount = 500
}
ud.setInteger(launchCount, forKey: "LaunchCount")
ud.synchronize()
// Do we clean DB?
if !clean {
sqlite3_close(db)
return
}
// Clean DB
print("SQLiteDB - Optimize DB")
let sql = "VACUUM; ANALYZE"
if execute(sql) != SQLITE_OK {
print("SQLiteDB - Error cleaning DB")
}
sqlite3_close(db)
}
}
// Execute SQL with parameters and return result code
func execute(sql:String, parameters:[AnyObject]?=nil)->CInt {
var result:CInt = 0
dispatch_sync(queue) {
let stmt = self.prepare(sql, params:parameters)
if stmt != nil {
result = self.execute(stmt, sql:sql)
}
}
return result
}
// Run SQL query with parameters
func query(sql:String, parameters:[AnyObject]?=nil)->[SQLRow] {
var rows = [SQLRow]()
dispatch_sync(queue) {
let stmt = self.prepare(sql, params:parameters)
if stmt != nil {
rows = self.query(stmt, sql:sql)
}
}
return rows
}
// Show alert with either supplied message or last error
func alert(msg:String) {
dispatch_async(dispatch_get_main_queue()) {
#if os(iOS)
let alert = UIAlertView(title: "SQLiteDB", message:msg, delegate: nil, cancelButtonTitle: "OK")
alert.show()
#else
let alert = NSAlert()
alert.addButtonWithTitle("OK")
alert.messageText = "SQLiteDB"
alert.informativeText = msg
alert.alertStyle = NSAlertStyle.WarningAlertStyle
alert.runModal()
#endif
}
}
// Private method which prepares the SQL
private func prepare(sql:String, params:[AnyObject]?)->COpaquePointer {
var stmt:COpaquePointer = nil
let cSql = sql.cStringUsingEncoding(NSUTF8StringEncoding)
// Prepare
let result = sqlite3_prepare_v2(self.db, cSql!, -1, &stmt, nil)
if result != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to prepare SQL: \(sql), Error: \(error)"
print(msg)
}
return nil
}
// Bind parameters, if any
if params != nil {
// Validate parameters
let cntParams = sqlite3_bind_parameter_count(stmt)
let cnt = CInt(params!.count)
if cntParams != cnt {
let msg = "SQLiteDB - failed to bind parameters, counts did not match. SQL: \(sql), Parameters: \(params)"
print(msg)
return nil
}
var flag:CInt = 0
// Text & BLOB values passed to a C-API do not work correctly if they are not marked as transient.
for ndx in 1...cnt {
// println("Binding: \(params![ndx-1]) at Index: \(ndx)")
// Check for data types
if let txt = params![ndx-1] as? String {
flag = sqlite3_bind_text(stmt, CInt(ndx), txt, -1, SQLITE_TRANSIENT)
} else if let data = params![ndx-1] as? NSData {
flag = sqlite3_bind_blob(stmt, CInt(ndx), data.bytes, CInt(data.length), SQLITE_TRANSIENT)
} else if let date = params![ndx-1] as? NSDate {
let txt = fmt.stringFromDate(date)
flag = sqlite3_bind_text(stmt, CInt(ndx), txt, -1, SQLITE_TRANSIENT)
} else if let val = params![ndx-1] as? Double {
flag = sqlite3_bind_double(stmt, CInt(ndx), CDouble(val))
} else if let val = params![ndx-1] as? Int {
flag = sqlite3_bind_int(stmt, CInt(ndx), CInt(val))
} else {
flag = sqlite3_bind_null(stmt, CInt(ndx))
}
// Check for errors
if flag != SQLITE_OK {
sqlite3_finalize(stmt)
if let error = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to bind for SQL: \(sql), Parameters: \(params), Index: \(ndx) Error: \(error)"
print(msg)
}
return nil
}
}
}
return stmt
}
// Private method which handles the actual execution of an SQL statement
private func execute(stmt:COpaquePointer, sql:String)->CInt {
// Step
var result = sqlite3_step(stmt)
if result != SQLITE_OK && result != SQLITE_DONE {
sqlite3_finalize(stmt)
if let err = String.fromCString(sqlite3_errmsg(self.db)) {
let msg = "SQLiteDB - failed to execute SQL: \(sql), Error: \(err)"
print(msg)
}
return 0
}
// Is this an insert
let upp = sql.uppercaseString
if upp.hasPrefix("INSERT ") {
// Known limitations: http://www.sqlite.org/c3ref/last_insert_rowid.html
let rid = sqlite3_last_insert_rowid(self.db)
result = CInt(rid)
} else if upp.hasPrefix("DELETE") || upp.hasPrefix("UPDATE") {
var cnt = sqlite3_changes(self.db)
if cnt == 0 {
cnt++
}
result = CInt(cnt)
} else {
result = 1
}
// Finalize
sqlite3_finalize(stmt)
return result
}
// Private method which handles the actual execution of an SQL query
private func query(stmt:COpaquePointer, sql:String)->[SQLRow] {
var rows = [SQLRow]()
var fetchColumnInfo = true
var columnCount:CInt = 0
var columnNames = [String]()
var columnTypes = [CInt]()
var result = sqlite3_step(stmt)
while result == SQLITE_ROW {
// Should we get column info?
if fetchColumnInfo {
columnCount = sqlite3_column_count(stmt)
for index in 0..<columnCount {
// Get column name
let name = sqlite3_column_name(stmt, index)
columnNames.append(String.fromCString(name)!)
// Get column type
columnTypes.append(self.getColumnType(index, stmt:stmt))
}
fetchColumnInfo = false
}
// Get row data for each column
let row = SQLRow()
for index in 0..<columnCount {
let key = columnNames[Int(index)]
let type = columnTypes[Int(index)]
if let val:AnyObject = self.getColumnValue(index, type:type, stmt:stmt) {
// println("Column type:\(type) with value:\(val)")
let col = SQLColumn(value: val, type: type)
row[key] = col
}
}
rows.append(row)
// Next row
result = sqlite3_step(stmt)
}
sqlite3_finalize(stmt)
return rows
}
// Get column type
private func getColumnType(index:CInt, stmt:COpaquePointer)->CInt {
var type:CInt = 0
// Column types - http://www.sqlite.org/datatype3.html (section 2.2 table column 1)
let blobTypes = ["BINARY", "BLOB", "VARBINARY"]
let charTypes = ["CHAR", "CHARACTER", "CLOB", "NATIONAL VARYING CHARACTER", "NATIVE CHARACTER", "NCHAR", "NVARCHAR", "TEXT", "VARCHAR", "VARIANT", "VARYING CHARACTER"]
let dateTypes = ["DATE", "DATETIME", "TIME", "TIMESTAMP"]
let intTypes = ["BIGINT", "BIT", "BOOL", "BOOLEAN", "INT", "INT2", "INT8", "INTEGER", "MEDIUMINT", "SMALLINT", "TINYINT"]
let nullTypes = ["NULL"]
let realTypes = ["DECIMAL", "DOUBLE", "DOUBLE PRECISION", "FLOAT", "NUMERIC", "REAL"]
// Determine type of column - http://www.sqlite.org/c3ref/c_blob.html
let buf = sqlite3_column_decltype(stmt, index)
// println("SQLiteDB - Got column type: \(buf)")
if buf != nil {
var tmp = String.fromCString(buf)!.uppercaseString
// Remove brackets
let pos = tmp.positionOf("(")
if pos > 0 {
tmp = tmp.subStringTo(pos)
}
// Remove unsigned?
// Remove spaces
// Is the data type in any of the pre-set values?
// println("SQLiteDB - Cleaned up column type: \(tmp)")
if intTypes.contains(tmp) {
return SQLITE_INTEGER
}
if realTypes.contains(tmp) {
return SQLITE_FLOAT
}
if charTypes.contains(tmp) {
return SQLITE_TEXT
}
if blobTypes.contains(tmp) {
return SQLITE_BLOB
}
if nullTypes.contains(tmp) {
return SQLITE_NULL
}
if dateTypes.contains(tmp) {
return SQLITE_DATE
}
return SQLITE_TEXT
} else {
// For expressions and sub-queries
type = sqlite3_column_type(stmt, index)
}
return type
}
// Get column value
private func getColumnValue(index:CInt, type:CInt, stmt:COpaquePointer)->AnyObject? {
// Integer
if type == SQLITE_INTEGER {
let val = sqlite3_column_int(stmt, index)
return Int(val)
}
// Float
if type == SQLITE_FLOAT {
let val = sqlite3_column_double(stmt, index)
return Double(val)
}
// Text - handled by default handler at end
// Blob
if type == SQLITE_BLOB {
let data = sqlite3_column_blob(stmt, index)
let size = sqlite3_column_bytes(stmt, index)
let val = NSData(bytes:data, length: Int(size))
return val
}
// Null
if type == SQLITE_NULL {
return nil
}
// Date
if type == SQLITE_DATE {
// Is this a text date
let txt = UnsafePointer<Int8>(sqlite3_column_text(stmt, index))
if txt != nil {
if let buf = NSString(CString:txt, encoding:NSUTF8StringEncoding) {
let set = NSCharacterSet(charactersInString: "-:")
let range = buf.rangeOfCharacterFromSet(set)
if range.location != NSNotFound {
// Convert to time
var time:tm = tm(tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0, tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0, tm_gmtoff: 0, tm_zone:nil)
strptime(txt, "%Y-%m-%d %H:%M:%S", &time)
time.tm_isdst = -1
let diff = NSTimeZone.localTimeZone().secondsFromGMT
let t = mktime(&time) + diff
let ti = NSTimeInterval(t)
let val = NSDate(timeIntervalSince1970:ti)
return val
}
}
}
// If not a text date, then it's a time interval
let val = sqlite3_column_double(stmt, index)
let dt = NSDate(timeIntervalSince1970: val)
return dt
}
// If nothing works, return a string representation
let buf = UnsafePointer<Int8>(sqlite3_column_text(stmt, index))
let val = String.fromCString(buf)
// println("SQLiteDB - Got value: \(val)")
return val
}
}
public extension String {
var NS: NSString { return (self as NSString) }
}
Hope you can give me some advice. Thanks

Get index of object from array of dictionary with key value

I have one array with dictionary.
Now i want to get index number of object with particular key value.
Like key = "xyz" and value = "abc".
I need index of object having above matching in dictionary.
{
Id = 20085;
IsNew = 1;
Title = Circular;
},
{
Id = 20088;
IsNew = 0;
Title = Query;
},
{
Id = 20099;
IsNew = 1;
Title = Blog;
},
{
Id = 20104;
IsNew = 1;
Title = News;
},
{
Id = 20172;
IsNew = 1;
Title = AssignTask;
},
{
Id = 20183;
IsNew = 1;
Title = Gallery;
},
{
Id = 20204;
IsNew = 1;
Title = Poll;
},
{
Id = 20093;
IsNew = 1;
Title = Assignment;
},
{
Id = 20209;
IsNew = 1;
Title = Activity;
},
{
Id = 20130;
IsNew = 1;
Title = Behaviour;
},
{
Id = 20180;
IsNew = 1;
Title = Result;
}
now i need index of object with having key = "Title" and value = "result"
You can use indexOf(_:) for this:
let index = array.indexOf{ $0["key"] == value }
In Swift 3.0, it's been renamed to index(Where:):
let index = array.index{ $0["key"] == value }
You can see this in action here.
Here is what you should be doing after using a json parser
let array:NSArray = [
[
"Id": 20130,
"IsNew": 1,
"Title":"Behaviour"
],
[
"Id": 20180,
"IsNew": 1,
"Title":"Result"
]]
let k = array as Array
let index = k.indexOf {
if let dic = $0 as? Dictionary<String,AnyObject> {
if let value = dic["Title"] as? String
where value == "Result"{
return true
}
}
return false
}
print(index) // index
I'd start with mapping the id values to an array, then getting the index of the id you're looking for.
func getIndexOf(itemID: Int) -> Int {
//Map out all the ids from the array of dictionaries into an array of Integers
let keysArray = dictionaries.map { (dictionary) -> Int in
return dictionary.value(forKey: "Id")
}
//Find the index of the id you passed to the functions
return keysArray.index(of: itemID)
}
other mainstream way to do this
func getIndex(of key: String, for value: String, in dictionary : [[String: Any]]) -> Int{
var count = 0
for dictElement in dictionary{
if dictElement.keys.contains(key) && dictElement[key] as! String == value{
return count
}
else{
count = count + 1
}
}
return -1
}
var sampleDict : [[String:Any]] = [
[
"Id" : 20130,
"IsNew" : 1,
"Title" : "Behaviour"
],
[
"Id" : 20130,
"IsNew" : 1,
"Title" : "Result"
],
]
let index = getIndex(of: "Title", for: "Result", in: sampleDict)
print(index)
This will print 1.
This answer is for the Swift 5.2 and above versions.
arr.append(["Title":titleName,"ID":1,"Result":true])
arr.append(["Title":titleName,"ID":2,"Result":true])
arr.append(["Title":titleName,"ID":3,"Result":true])
arr.append(["Title":titleName,"ID":4,"Result":true])
This is an array of dictionary format. And if you want to find an index of an object where ID == 3
func findIndex(Id : Int ) -> Int? {
guard let index = arr.firstIndex(where: {
if let dic = $0 as? Dictionary<String,AnyObject> {
if let value = dic["ID"] as? Int, value == Id {
return true
}
}
return false
}) else { return nil }
return index
}
let myIndex = findIndex(3)
self.arr.insert( ["Title":titleName,"ID":10,"Result":true]) at: myIndex)

Ignore a letter in swift which starts with a Lower Case

Here's what I am trying to do :
let courseName = "Bachelor of Tourism Administration(B.T.A)".condensedWhitespace
let upperCaseCourseName = courseName.uppercaseString
let extrctCourseName = upperCaseCourseName.componentsSeparatedByString(" ").reduce("") { $0.0 + String($0.1.characters.first!) }
let upperCasecourseFirstCharcters = extrctCourseName
print(upperCasecourseFirstCharcters) // output : "BOTA" but i want "BTA"
as you see that my outPut of "Bachelor of Tourism Administration(B.T.A)" is BOTA but the desired output is BTA because word of is starting from a lowerCase and i want to ignore that word in my this method , how am gonna do that any idea ?
let courseName = "Bachelor of Tourism Administration(B.T.A)" //.condensedWhitespace
var newString = ""
let array : NSArray = courseName.componentsSeparatedByString(" ")
for chr in array {
let str = chr as! NSString
if str.lowercaseString != str{
if newString.characters.count > 0{
newString = newString.stringByAppendingString(" "+(str as String))
continue
}
newString = newString.stringByAppendingString((str as String))
}
}
let upperCaseCourseName = newString.uppercaseString
let extrctCourseName = upperCaseCourseName.componentsSeparatedByString(" ").reduce("") { $0.0 + String($0.1.characters.first!) }
let upperCasecourseFirstCharcters = extrctCourseName
print(upperCasecourseFirstCharcters)
//This will defiantly meet to your problem/. Let me know if it works for u or not
You can paste this into a playground:
extension String {
func array() -> [String] {
return self.componentsSeparatedByString(" ")
}
func abbreviate() -> String {
var output = ""
let array = self.array()
for word in array {
let index = word.startIndex.advancedBy(0)
let str = String(word[index])
if str.lowercaseString != str {
output += str
}
}
return output
}
}
let courseName = "Bachelor of Tourism Administration(B.T.A)".abbreviate()
print(courseName) // prints BTA
A clean approach would be:
extension Character
{
public func isUpper() -> Bool
{
let characterString = String(self)
return (characterString == characterString.uppercaseString) && (characterString != characterString.lowercaseString)
}
}
let courseName = "Bachelor of Tourism Administration(B.T.A)"
let upperCaseCourseName = courseName
let extrctCourseName = upperCaseCourseName.componentsSeparatedByString(" ").reduce("") {
if($0.1.characters.first!.isUpper()) {
return $0.0 + String($0.1.characters.first!)
}else {
return $0.0
}
}

Breadth First Search: Shortest Reach (BFS)

https://www.hackerrank.com/challenges/bfsshortreach
My strategy is to keep an array of the Node and its corresponding adjacent nodes using an integer and unordered set.
Then I start at the starting node and iterate throughout, keeping a set of all the corresponding adjacent nodes and terminating if I visit any node I've already visited.
Thanks for any Swifters willing to help me! Spent a day trying to figure it out and it's driving me crazy. :(
let testCases : Int = Int(readLine()!)!
for i in 0..<testCases
{
let inputArray : [Int] = String(readLine()!).characters.split(" ").map{Int(String($0))!}
let numberOfNodes : Int = inputArray[0]
let numberOfEdges : Int = inputArray[1]
var dictionary : [Int : Set<Int>] = [:]
var countDictionary : [Int : Int] = [:]
for j in 0..<numberOfEdges
{
let edge : [Int] = String(readLine()!).characters.split(" ").map{Int(String($0))!}
let start : Int = edge[0]
let end : Int = edge[1]
if let val = dictionary[start]
{
dictionary[start]!.insert(end)
}
else
{
dictionary[start] = Set.init(arrayLiteral: end)
}
if let val = dictionary[end]
{
dictionary[end]!.insert(start)
}
else
{
dictionary[end] = Set.init(arrayLiteral: start)
}
}
let temp : [Int] = String(readLine()!).characters.split(" ").map{Int(String($0))!}
let startPoint : Int = temp[0]
var traversed : Set<Int> = Set()
func iterate(node : Int, _ count : Int)
{
let newCount = count + 6
var temp : [Int] = []
if let val = dictionary[node]
{
for i in val
{
temp.append(i)
}
}
if let val = countDictionary[node]
{
if count < val
{
countDictionary[node]! = count
}
}
else
{
countDictionary[node] = count
}
if traversed.contains(node)
{
return
}
traversed.insert(node)
for j in temp
{
iterate(j, newCount)
}
}
iterate(startPoint, 0)
for z in 0..<numberOfNodes
{
if let val = countDictionary[z + 1]
{
if val > 0
{
print(val, terminator: " ")
}
}
else
{
print(-1, terminator: " ")
}
}
print(" ")
}

Resources