Another App updated to the newest iOS version!
Project Time Log has been rebuilt in Swift, with updated API’s for DropBox and SQLite. After five years (first version in 2012!) still up and running!

Project Time Log in the AppStore

The goal of Project Time Log is to keep track of time you’ve spent on projects. There are three main actions:

1. Add one or more projects;
2. Start the timer for the project you start working on. Stop the timer when you stop working. You can repeat this as often as you wish;
3. View the log to learn how much time you’ve spent on your projects (per timer, per day and in total).

In addition to these actions you can:
– change project properties any time;
– make changes to your logs or add/delete logs manually: this comes in handy when you forgot to stop or start the timer;
– use the build-in notification system to alert you when a certain amount of time has been exceeded.
– export your logs for use in an external spreadsheet.
– backup and restore your data.

Project Time Log has been designed to be intuitively simple. The best way to get to know it is by testing and trying. There is a predefined ‘test project’ which you can use for that purpose. When finished testing you can delete it without any consequences.

A powerful feature of Project Time Log is that once you’ve started a timer, it will simply keep on counting until you stop it, even when your device is completely switched off.

Best solution for using SQLite in your Swift project is SQLite Swift. It works perfect and comes with very good documentation.

A problem I was facing was converting a field value to an integer.

In short, this was the problematic code:


let db = try Connection(databasePath)
let stmt = try db.prepare("SELECT someId, someCount, someName FROM someTable")
        
for row in stmt {
    print("row[1] = \(String(describing: row[1]))")
    // ... I need row[1] as Integer!
}

I needed to convert row[1] to an Integer.
I tried many solution, found on multiple forums, none of them really worked.
Finally I came up with this:


let db = try Connection(databasePath)
let stmt = try db.prepare("SELECT someId, someCount, someName FROM someTable")
        
for row in stmt {
    let optionalCount : Int64 = Optional(row[1]) as! Int64
    let lCount = Int(optionalCount)
    // Now I have an integer!

 }

Happy Coding!

The fastest way of coding is doing a lot of copy-paste. I know, you shouldn’t. But most of us do … so lets be honest about that 🙂

Following some copy-paste-ready Swift code for sending e-mails form your iOS app.



//  MailerViewController.swift

import UIKit

import MessageUI

class MailerViewController: UIViewController, MFMailComposeViewControllerDelegate {

override func viewDidLoad() {

super.viewDidLoad()

let mSubject = "The subject of the e-mail"

let mBody = "Hi! This is an e-mail. Please se the attached file."

let mRecipients = ["info@devjockeys.com", "martin@devjockeys.com", "some_recipient@some_email.com"]

let mAttachment = "Some content".data(using: String.Encoding.utf8, allowLossyConversion: false)!

let mAttachmentName = "attachment_filename.txt"

doEmail(subject: mSubject, body: mBody, recipients: mRecipients, attachment: mAttachment, attachmentName: mAttachmentName)

}

func doEmail(subject: String, body: String, recipients: Array, attachment: Data, attachmentName: String ) {

if MFMailComposeViewController.canSendMail() {

let mailer = MFMailComposeViewController()

mailer.mailComposeDelegate = self

// the subject
mailer.setSubject(subject)

// the recepients: an Array of Strings
mailer.setToRecipients(recipients)

// make an attachment. You can attach anything, as long as it is a "Data?" object
mailer.addAttachmentData(attachment, mimeType: "application/octet-stream", fileName: attachmentName)

// the message body
mailer.setMessageBody(body, isHTML: false)

// present the mailer
self.present(mailer, animated: true, completion: nil)

}

else

{

let alert = UIAlertController(title: "Mail Error", message: "Your device has not been configured to send e-mails", preferredStyle: .alert)

let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)

alert.addAction(okAction)

self.present(alert,animated: true,completion: nil)

}
}

// mailer delegate

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {

var  message = ""

switch (result)

{

case .cancelled: message = "You cancelled the operation and no e-mail message was sent."
case .saved: message = "You saved the e-mail message in the drafts folder."
case .sent: message = "Mail send: e-mail message sent successfully."
case .failed: message = "Mail failed: the e-mail message was not sent. Please check your e-mail settings."

}

let alert = UIAlertController(title: "Mailer", message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okAction)

self.present(alert,animated: true,completion: nil)

// Remove the mail view
self.dismiss(animated: true, completion: nil)

}

}

 

This code sample demonstrates how you can reorder an array.

A possible scenario is when you have multiple-choise questions that you want to present in a different order every time they are shown.

var arrUniqueNumbers = [1,2,3,4]        
print("Array before shuffle: \(arrUniqueNumbers)")    
let count = arrUniqueNumbers.count
for i in 0..<count{
            let n = Int(arc4random_uniform(UInt32(count-i)))+i            
            (arrUniqueNumbers[i], arrUniqueNumbers[n]) = 
                              (arrUniqueNumbers[n], arrUniqueNumbers[i])
           }
print("Array after shuffle: \(arrUniqueNumbers)")