How to display indian and euro locale number value in words? - ios

I am struggling to show the Indian and Euro Locale value in words. Please anyone help on this.
var outputString = ""
let valueString = "9,58,888.875"
let valueFormatter = NSNumberFormatter()
let outputFormatter = NSNumberFormatter()
outputFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
valueFormatter.numberStyle = NSNumberFormatterStyle.SpellOutStyle
outputString = valueFormatter.stringFromNumber(outputFormatter.numberFromString(valueString as String)!)!
print(outputString)

I know it's very late. I have tried following solution, might not the best one but it's working for me. Hope it will be useful.
Note: - I have considered only till crore scale
#IBAction func startBtnClicked(sender: AnyObject) {
if var amountStr = ammountTextField.text
{
let numberFormater = NSNumberFormatter()
if amountStr.containsString(",")
{
amountStr = amountStr.stringByReplacingOccurrencesOfString(",", withString: "")
}
//eg: - amountStr = "45678432"
if let amountNumber = numberFormater.numberFromString(amountStr)
{
//First get currency format
let currencyFormatter = NSNumberFormatter()
currencyFormatter.numberStyle = .CurrencyStyle
currencyFormatter.currencySymbol = ""
currencyFormatter.locale = NSLocale(localeIdentifier: "en_IN")
let amountInCurrencyFormatStr = currencyFormatter.stringFromNumber(amountNumber)
//amountInCurrencyFormatStr = "4,56,78,432"
var outputStr = ""
//Get each component in array
if let amountInCurrencyFormatComponentArray = amountInCurrencyFormatStr?.componentsSeparatedByString(",")
{
//[4,56,78,432]
let scaleStrArr = ["thousand","lakh","crore"]
let spellFormatter = NSNumberFormatter()
spellFormatter.numberStyle = .SpellOutStyle
var scaleStrCount = 0
for var i = (amountInCurrencyFormatComponentArray.count - 1) ; i >= 0 ; i--
{
//Iterate array, and append scale strings (["thousand","lakh","crore"]) at proper place
if let currencyStr = spellFormatter.stringFromNumber(numberFormater.numberFromString(amountInCurrencyFormatComponentArray[i])!)
{
if i == (amountInCurrencyFormatComponentArray.count - 1)
{
outputStr = currencyStr
}
else
{
if scaleStrCount < scaleStrArr.count
{
outputStr = "\(currencyStr) \(scaleStrArr[scaleStrCount]) \(outputStr)"
scaleStrCount++
}
else
{
outputStr = "\(currencyStr) \(outputStr)"
}
}
}
else
{
print("ERROR: - Unable to spell")
}
}
}
else
{
print("ERROR: - No , in text field")
}
ammountTextField.text = amountInCurrencyFormatStr
print("OUTPUT --> \(outputStr)")
//OUTPUT -> "four crore fifty-six lakh seventy-eight thousand four hundred thirty-two"
}
else
{
print("ERROR: - No Number in text field")
}
}
else
{
print("ERROR: - No value in text field")
}
}

Related

Swift, converting a number to string, number gets rounded down

I'm having a bit of issue with my code...right now, I am passing a string containing a bunch of numbers, to get converted to a number, comma separators added, then converted back to a string for output. When I add a decimal to my string and pass it in, a number like 996.3658 get truncated to 996.366...
"currentNumber" is my input value, "textOutputToScreen" is my output...
func formatNumber() {
let charset = CharacterSet(charactersIn: ".")
if let _ = currentNumber.rangeOfCharacter(from: charset) {
if let number = Float(currentNumber) {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
guard let formattedNumber = numberFormatter.string(from: NSNumber(value: number)) else { return }
textOutputToScreen = String(formattedNumber)
}
}
else {
if let number = Int(currentNumber) {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
guard let formattedNumber = numberFormatter.string(from: NSNumber(value: number)) else { return }
textOutputToScreen = String(formattedNumber)
}
}
}
Thank you in advance for your help!
The issue there is that you have to set your NumberFormatter minimumFractionDigits to 4. Btw there is no need to initialize a NSNumber object. You can use Formatters string(for: Any) method and pass your Float. Btw I would use a Double (64-bit) instead of a Float (32-bit) and there is no need to initialize a new string g from your formattedNumber object. It is already a String.
Another thing is that you don't need to know the location of the period you can simply use contains instead of rangeOfCharacter method. Your code should look something like this:
extension Formatter {
static let number: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
}
func formatNumber(from string: String) -> String? {
if string.contains(".") {
guard let value = Double(string) else { return nil }
Formatter.number.minimumFractionDigits = 4
return Formatter.number.string(for: value)
} else {
guard let value = Int(string) else { return nil }
Formatter.number.minimumFractionDigits = 0
return Formatter.number.string(for: value)
}
}
let label = UILabel()
let currentNumber = "996.3658"
label.text = formatNumber(from: currentNumber) // "996.3658\n"
If you would like to assign the result to your var instead of a label
if let formatted = formatNumber(from: currentNumber) {
textOutputToScreen = formatted
}

I am trying to get an icon array to display in my weather app, but can not seem to get UIImage to display them

This is my code so far, with no errors, but it is not picking the dates from the 5 day forecast. What is wrong in this code?
//: to display the 5 day date array from the open weather API
enter code herevar temperatureArray: Array = Array()
var dayNumber = 0
var readingNumber = 0
if let jsonObj = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary {
if let mainArray = jsonObj!.value(forKey: "list") as? NSArray {
for dict in mainArray {
if let mainDictionary = (dict as! NSDictionary).value(forKey: "main") as? NSDictionary {
if let temperature = mainDictionary.value(forKey: "temp_max") as? Double {
if readingNumber == 0 {
temperatureArray.append(temperature)
} else if temperature > temperatureArray[dayNumber] {
temperatureArray[dayNumber] = temperature
}
} else {
print("Error: unable to find temperature in dictionary")
}
} else {
print("Error: unable to find main dictionary")
}
readingNumber += 1
if readingNumber == 8 {
readingNumber = 0
dayNumber += 1
}
var dateArray: Array<String> = Array()
var dayNumber = 0
var readingNumber = 0
if let weatherArray = jsonObj!.value(forKey: "list") as? NSArray {
for dict in weatherArray {
if let weatherDictionary = (dict as! NSDictionary).value(forKey: "list") as? NSDictionary {
if let date = weatherDictionary.value(forKey: "dt_txt") as? String {
if readingNumber == 0 {
dateArray.append(date)
} else if date > dateArray[dayNumber] {
dateArray[dayNumber] = date
}
}
} else {
print("Error: unable to find date in dictionary")
}
readingNumber += 1
if readingNumber == 8 {
readingNumber = 0
dayNumber += 1
}
}
}
}
}
}
func fixTempForDisplay(temp: Double) -> String {
let temperature = round(temp)
let temperatureString = String(format: "%.0f", temperature)
return temperatureString
}
DispatchQueue.main.async {
self.weatherLabel1.text = "Today: (fixTempForDisplay(temp: temperatureArray[0]))°C"
self.weatherLabel2.text = "Tomorrow: (fixTempForDisplay(temp: temperatureArray[1]))°C"
self.weatherLabel3.text = "Day 3: (fixTempForDisplay(temp: temperatureArray[2]))°C"
self.weatherLabel4.text = "Day 4: (fixTempForDisplay(temp: temperatureArray[3]))°C"
self.weatherLabel5.text = "Day 5: (fixTempForDisplay(temp: temperatureArray[4]))°C"
func formatDate(date: NSDate) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
return dateFormatter.string(from: date as Date)
}
self.dateLabel1.text = ": \(formatDate(date: dateArray[0]))"
self.dateLabel2.text = ": \(formatDate(date: dateArray[1]))"
self.dateLabel3.text = ": \(formatDate(date: dateArray[2]))"
self.dateLabel4.text = ": \(formatDate(date: dateArray[3]))"
self.dateLabel5.text = ": \(formatDate(date: dateArray[4]))"
}
}
}
dataTask.resume()
}
}
It looks to me like you need to change your icon array to contain strings
var iconArray: Array<String> = Array()
and then when parsing the json text
if let icon = weatherDictionary.value(forKey: "icon") as? String {
and finally
self.iconImage1.image = UIImage(named: iconArray[0])
self.iconImage2.image = UIImage(named: iconArray[1])
Of course the below comparison won't work anymore when icon is a string but I don't understand any of this if/else clasue so I don't know what to replace it with
if readingNumber == 0 {
iconArray.append(icon)
} else if icon > iconArray[dayNumber] { //This won't work now.
iconArray[dayNumber] = icon
}

Adding Thousand Separator Automatically (Swift)

I have a code for my calculator
How could I do so that when the user would enter the numbers he would be separated by a space automatically?
I've been trying to find an answer for a long time, but nothing fits that it was displayed right away
var currentInput: Double {
get {
return Double (displayResultLabel.text!)!
}
set {
let value = "\(newValue)"
let ValueArray = (value.components(separatedBy:"."))
if ValueArray[1] == "0" {
displayResultLabel.text = "\(ValueArray[0])"
} else {
displayResultLabel.text = "\(newValue)"
}
stillTyping = false
}
}
#IBAction func numberPressed(_ sender: UIButton) {
let number = sender.currentTitle!
if stillTyping {
if (displayResultLabel.text?.characters.count)! < 14 {
displayResultLabel.text = displayResultLabel.text! + number
}
} else {
displayResultLabel.text = number
stillTyping = true
}
}
Then what happened:
#IBAction func numberPressed(_ sender: UIButton) {
let number = sender.currentTitle!
if stillTyping {
if (displayResultLabel.text?.characters.count)! < 14 {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let newNumber = NSNumber(value: Double(displayResultLabel.text! + number)!)
displayResultLabel.text = formatter.string(from: newNumber)
}
} else {
displayResultLabel.text = number
stillTyping = true
}
}
Error
var stillTyping = false
var dotIsPlaced = false
var firstOperand: Double = 0
var secondOperand: Double = 0
var operationSign: String = ""
It is better to accumulate your value in a separate string that doesn't have the formatting applied rather than using the text field as your data model. You can then format the decimal and display it in the label as required using a NumberFormatter:
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
var currentInput: String = "0" {
didSet {
self.displayResultLabel?.text = self.currentDisplay
}
var currentValue: Double {
return Double(self.currentInput) ?? 0
}
var currentDisplay: String {
return formatter.string(from: NSNumber(value:self.currentValue)) ?? "0"
}
func addDigit(_ digit: Int) {
if currentInput.count < 14 {
let newValue = self.currentValue * 10 + Double(digit)
self.currentInput = "\(newValue)"
}
}
#IBAction func numberPressed(_ sender: UIButton) {
guard let digit = Int(sender.currentTitle!) else {
return
}
self.addDigit(digit)
}
This is what NumberFormatters are for
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
if let newNumber = formatter.number(from: displayResultLabel.text! + number){
displayResultLabel.text = formatter.string(from: newNumber)
}
Note that NumberFormatters go both ways, and you can (and probably should) use them to parse numbers from strings, too

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

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
}
}

Resources