Swift Snippets 4: Numbers, Dates, Unified log, Objective-C


Useful tricks with numbers.

Get maximum, minimum, and total of an array of numbers (here integers)
let addTwo: (Int, Int) -> Int = { x, y in x + y }
let sortedNumbers = copiedNumbers.sorted(by: <)
let theMin = sortedNumbers.first!
let theMax = sortedNumbers.last!
let theTotal = sortedNumbers.reduce(0, addTwo)

Date formats

Using Date (NSDate) and DateFormatter.

Use DateFormatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSSSZZZ"
tempDate = dateFormatter.date(from: dateStampString)

using correct formatting string.

Get the period in decimal seconds since the present time
let timeSinceLast = theEventTime.timeIntervalSinceNow
Get the period in decimal seconds between firstDate and anotherDate
let timeSince = firstDate.timeIntervalSince(anotherDate)
Be careful with the sign of the result.

Get a date and time far into the future
neverNever = NSDate.distantFuture

Make an empty array of dates
var startBU = [Date]()
then at start of code to use
startBU = [Date]()

Unified log

Using Sierra’s new unified log.

Implement as a class with static strings. By default, any mutable strings are written out to log as <private>, which is unhelpful. The public formatting override bypasses that, but only when used as shown, not as %{public}s.
import os.log
public class Demo {
static let gen_log = OSLog(subsystem: "co.mycompany.appname", category: "general")
public init() {
func writeLogEntry(type: OSLogType) {
os_log("Any static string", log: Demo.gen_log, type: type)
func writeLogEntry(type: OSLogType, number: Int) {
os_log("Here's an integer: %d", log: Demo.gen_log, type: type, number)
func writeLogEntry(type: OSLogType, string: String) {
os_log("%{public}@", log: Demo.gen_log, type: type, string)

Call as
let myDemo = Demo()
myDemo.writeLogEntry(type: .debug, number: intParam!)
myDemo.writeLogEntry(type: .debug, string: anyString)

also simple static string entry
os_log("This is the message.")


Working with old Objective-C and C interfaces.

Don’t literally try passing NULL. Use e.g.
let theChain: SecKeychain? = nil
let theAccess: UnsafeRawPointer? = nil
let theResult2 = SecKeychainUnlock(theChain, 0, theAccess, false)

When a call returns a CFString? e.g.
let theReserved: UnsafeMutableRawPointer? = nil
let theSctring = SecCopyErrorMessageString(theResult2, theReserved)
theResString = theSctring! as String

and you can then

Passing a buffer into which a null-terminated C string will be written
var theStrBuff = Array(repeating: 0 as Int8, count: 1024)
var theLength: UInt32 = 1024
let theResult4 = SecKeychainGetPath(theDefKeychain, &theLength, &theStrBuff)
if (theResult4 != 0) {
displayError(status: theResult4, fname: "SecKeychainGetPath")
} else {
theDefKeychainPath = FileManager().string(withFileSystemRepresentation: theStrBuff, length: Int(theLength))
let theStr = String(theDefKeychainPath)

TheStrBuff does not need to be explicitly deallocated, and theStr is a Swift String.

Swift Snippets 0: Introduction and Contents

(Updated 2 July 2017.)