Author: Mathias Lipowski

Xcode fails to generate source files from intent definition files when using the Legacy Build System

The workaround for this problem is the following: First, add a Run Script phase before the Compile Sources phase of your target:

xcrun intentbuilderc generate -input ${SRCROOT}/PATH/TO/Intents.intentdefinition -output ${SRCROOT}/Intents -classPrefix "" -language Swift -swiftVersion 5.0

Then, add all of the generated files from the output path specified in the command above to all required targets in your project.

Source: https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_release_notes

Change default reading font in Outlook from Times New Roman to Calibri (or any other)

I use Outlook 2016 and some emails are shown in Times New Roman, even if the default font was set to Calibri. This is the case, when HTML mails do not have any CSS style. In this case, Outlook uses the default fall back font Times New Roman. It took me some time to realise that there is no setting for this in Outlook.

But: the related setting can be found in Word 2016 (yes, Word!).

To change the setting, open Word and go to:

File > Options > Advanced > General section > Web Options… > Fonts tab > Proportional font …

There you can change the setting with Times New Roman font to any other font. After the change you have to restart Outlook. Each unformated HTML mail should now be displayed in the selected font.

Photo by Federica Galli on Unsplash.

Background tasks in iOS

As already discussed in Background task in iOS action extension, it sometimes becomes necessary to perform time consuming tasks in the background. This is really important, if such a task would block the user interaction. Especially for action and share extensions, this might lead to some waiting time before a task completes and the extension disappears. After several attempts to realise a working solution, the following code help to extends an App’s background execution time.

This code was described in the article Extending Your App’s Background Execution Time.

Extending the background execution time in an app

func performTask()
{
   // Perform the task on a background queue.
   DispatchQueue.global().async {
      // Request the task assertion and save the ID.
      self.backgroundTaskID = UIApplication.shared.
                 beginBackgroundTask (withName: "Perform Long Task") {
         // End the task if time expires.
         UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
         self.backgroundTaskID = UIBackgroundTaskInvalid
      }
            
      // Run task synchronously.
      self.performLongTask()
            
      // End the task assertion.
      UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
      self.backgroundTaskID = UIBackgroundTaskInvalid
   }
}

Extending the background execution time in an extension

func performTask()
{
   // Perform the task in background.
   let processinfo = ProcessInfo()
   processinfo.performExpiringActivity(withReason: "Long task") { (expired) in
      if (!expired) {
         // Run task synchronously.
         self.performLongTask()
      }
      else {
         // Cancel task.
         self.cancelLongTask()
      }
   }
}

As mentioned in the documentation, the ProcessInfo code block is called a second time if the system need to suspend the process:

If your block is still executing and the system need to suspend the process, the system executes your block a second time with the expired parameter set to true. Your block must be prepared to handle this case. When the expired parameter is true, stop any in-progress tasks as quickly as possible.

Source: https://developer.apple.com/documentation/foundation/processinfo/1617030-performexpiringactivity

Important: it’s important that the tasks are executed synchronously. When the end of the block is reached, the thread will terminate and end the execution of your task. If your tasks are asynchron, you can use a loop like shown below to wait inside the background thread until the asynchron task is finished:

// Keep background thread alive until asynchron task ends.
repeat {
    sleep(1)
} while(taskIsRunning)

General thoughts on using background tasks in iOS

A good summary of background tasks is available at https://forums.developer.apple.com/thread/85066


Photo by Jonathan Borba on Unsplash.

Note To Self: how to instantly create tasks in Trello

If you are using the mail import feature of Trello, you can speed up the notes with Note To Self Mail. The app creates notes in Trello in seconds.

Setup Note To Self Mail for Trello

1. Get your Trello email address

Get your Trello email address by open up one of your boards in Trello and go to “Email-to-board Settings” ind the settings section of the sidebar. Emails sent to this address will appear as a task in this board. The subject of the email will become the title and the body will become the description.

2. Add your Trello email address to Note To Self Mail

Add this email address to Note To Self Mail. You can also set the label to “Trello” or any other descriptive name.

Note To Self Mail > Settings > Add email …

3. Adjust the subject

Trello uses the subject as a main source of a new note. Set the subject to “Use first line of note”. This ensures, that the first line is used as subject and all the other text lines are moved to the description of the task.

Note To Self Mail > Settings > Add email … > Subject

Usage

There are some shortcuts or special chars that can be used in the subject of the mail. All available features are described in Trello’s documentation: Formatting Tips (opens in a new tab)”>Creating cards by email > Formatting Tips.

Now, you can send any note to Trello. With the following text …

… a new task will be created in Trello …

You might notice, that the task was placed in the correct list (as set in Trello) and was tagged with “home”. All the other contents of the input (line 2 up to the end) are moved to the task description. That’s it!

Note To Self: how to quickly create tasks in OmniFocus

If you are using the email capture / mail drop feature of OmniFocus, you can speed up the notes with Note To Self Mail. The app creates notes in OmniFocus in seconds.

Setup Note To Self Mail for OmniFocus

1. Create your OmniFocus email address

If you’re already using the Omni Sync Server to sync OmniFocus, you can log in to the sync server web interface and create your first Mail Drop address. After logging in, just click the Create Address button to automatically generate the email address (a combination of your account name and a random string of characters, for example).

2. Add your OmniFocus email address to Note To Self Mail

Add this email address to Note To Self Mail. You can also set the label to “OmniFocus” or any other descriptive name.

Note To Self Mail > Settings > Add email …

3. Adjust the subject

OmniFocus uses the subject as a main source of a new note. Set the subject to “Use first line of note”. This ensures, that the first line is used as subject and all the other text lines are moved to the body.

Note To Self Mail > Settings > Add email … > Subject

Usage

In OmniFocus, the subject line of that message becomes the name of the new Inbox item. The body of the message becomes the Note, which can contain text, attachments (such as images and files), and simple HTML (more complex formatting is removed). All available features are described in OmniFocus documentation: Capture Methods > Email Capture (Mail Drop).

Now, you can send any note to OmniFocus. With the following text …

… a new task will be created in your Inbox.

You might notice, that the first line is used as title. All the other contents of the input (line 2 up to the end) are moved to the task description. That’s it!

Note To Self: how to create tasks in Asana – the fast way

If you are using the mail import feature of Asana, you can speed up the notes with Note To Self Mail. The app creates notes in Asana in seconds.

Setup Note To Self Mail for Asana

You can create tasks and conversations from email addresses associated with Asana. Check which email address is associated by open up Asana and go to “My Profile Settings > Email Forwarding”.

1. Add the Asana email address to Note To Self Mail

Add the Asana email address x@mail.asana.com to Note To Self Mail. You can also set the label to “Asana” or any other descriptive name.

You can create conversations by using [team-name]@mail.asana.com. For example, marketing@mail.asana.com goes to the Marketing team, and customer-success@mail.asana.com goes to the Customer Success team.

Note To Self Mail > Settings > Add email …

2. Adjust the subject

Asana uses the subject as a main source of a new note. Set the subject to “Use first line of note”. This ensures, that the first line is used as subject and all the other text lines are moved to the description of the task.

Note To Self Mail > Settings > Add email … > Subject

3. Check your “from” email address

When using Gmail, your login id is used as sender address. If you use a custom SMTP server, you can specify the sender email in SMTP settings. In this case you have to make sure that this email is the same as the one used in Asana settings (see 1.).

Usage

Now, you can send any task to Asana. Tasks emailed will appear in your My Tasks list.

  • The subject line will be the task name
  • The body will be the task description
  • All email attachments will be attached to the task
  • You can cc teammates to add them as task collaborators

A detailed description of the possibilities are listed in Asana’s documentation: Emailing Tasks.

Now, you can send any note to Asana. With the following text …

… a new task will be created in Asana …

You might notice, that the task was placed in the correct project. The subject is set to the task title. All the other contents of the input (line 2 up to the end) are moved to the task description. That’s it!

Black or white text on a colour background?

How to calculate programmatically whether black text or white text is more readable on a colour background?

Here are some algorithms to calculate the brightness of a color. The example code is written in PHP, but you should be able to adapt the code examples to any other programming language. All of the algorithmns are applied on the following color map to have a first impression how they perform.

Arithmetic Mean

f'(x)= \frac{a+b+c}{3}

In Code, this looks like:

function arithmeticMean($hex)
{
    $rgb = ColorUtils::hex2rgb($hex);
    return ($rgb[0] + $rgb[1] + $rgb[2]) / 3;
}

This results in an output for black/white text like:

This is a very simple and effective algorithm. Unfortunately it fails between the green and turquoise region:

The quick brown fox jumps over the lazy dog

Geometric Mean

f'(x)=\sqrt[n]{rgb}

In Code, this looks like:

function geometricMean($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return pow($rgb[0] * $rgb[1] * $rgb[2], 1/3);
}

This results in an output for black/white text like:

Now the text is much better with the green background, but now the brightness of the yellow is wrong:

The quick brown fox jumps over the lazy dog

Quadratic Mean

f'(x)= \sqrt{\frac{r^2 +g^2+ b^2}{3}}

In Code, this looks like:

function quadraticMean($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return sqrt( (pow($rgb[0], 2) + pow($rgb[1], 2) + pow($rgb[2], 2)) / 3);
}

This results in an output for black/white text like:

Works really well for all dark colours. Fails on purple.

The quick brown fox jumps over the lazy dog

HSV Value (Brightest Component)

f'(x)= max(r,g,b)

In Code, this looks like:

function valueFromHSV($hex)
{
    var $hsv = ColorUtils::hex2hsv($hex);
    return $hsv[2] * 255;
}

This results in an output for black/white text like:

Dark colours are ok, Fails when the r, g or b value is close to 0x99.

Darkest Component

f'(x)= min(r,g,b)

In Code, this looks like:

function valueFromHSV($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return min($rgb[0], $rgb[1], $rgb[2]);
}

This results in an output for black/white text like:

Only the very bright colours work fine with this algorithm.

The quick brown fox jumps over the lazy dog

3D distance in RGB space

f'(x)= \sqrt{r^2 +g^2+ b^2}

In Code, this looks like:

function distanceIn3D($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return sqrt( pow($rgb[0], 2) + pow($rgb[1], 2) + pow($rgb[2], 2));
}

This results in an output for black/white text like:

Worse than using the V component of the HSV representation.

The quick brown fox jumps over the lazy dog

Lightness From HSL

In Code, this looks like:

function lightnessFromHSL($hex)
{
    var $hsl = ColorUtils::hex2hsl($hex);
    return $hsl[2] * 255;
}

This results in an output for black/white text like:

The best unweighted formula. Fails on yellow around 0xeeee00.

The quick brown fox jumps over the lazy dog

Weighted W3C Formula

Natural formulas don’t take into consideration that the human eye perceives some of the primary colours darker than others.

Eg pure green(0xff0000) is perceived brighter than pure blue(0x00ff00).
According to the W3C consortium, this biased perception can be modelled with the following weights:

r *= .299
g *= .587
b *= .111
f'(x)= r\cdot0.299 +g\cdot0.587+ b\cdot0.111

In Code, this looks like:

function weightedW3C($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return $rgb[0] * 0.299 + $rgb[1] * 0.587 + $rgb[2] * 0.114;
}

This results in an output for black/white text like:

Very good algorithm, works really well.
Source: http://www.w3.org/TR/AERT#color-contrast

The quick brown fox jumps over the lazy dog

Weighted Distance in 3D RGB Space

f'(x)= \sqrt{r^2\cdot0.241 +g^2\cdot0.691+ b^2\cdot0.068}

In Code, this looks like:

function weightedDistanceIn3D($hex)
{
    var $rgb = ColorUtils::hex2rgb($hex);
    return sqrt(pow($rgb[0], 2) * 0.241 + pow($rgb[1], 2) * 0.691 + pow($rgb[2], 2) * 0.068);
}

This results in an output for black/white text like:

This is an improved version of the W3C fomula.
Source: http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx

The quick brown fox jumps over the lazy dog

ColorUtils

The used ColorUtils class above consists of methods that are used to convert colors between different color spaces. The library is available here.

If you are interested in the source code to generate the color map examples above:


Photo by Markus Spiske on Unsplash. Image map by Wikimedia Commons.