Wednesday, May 18, 2016

NSRegularExpression... String? NSRange? Wha...? (Swift 2.2)

Trying to work with NSRegularExpression in Swift, I came across this common issue: to get matches, you must provide a Swift String to match on. However, NSRegularExpression returns NSRange objects representing any resulting matches. Problem is, String and NSRange don't play well with each other!

To work around this, as usual, I'll give you the short of the story, followed by the details.

The Short Story:
Convert your resulting NSRange match items into Range items with the original string's String.UTF16View representation. UTF16View has a samePositionIn(String) function ready-made for this purpose!

Example code:

// Note: all types are specified for clarity //
// set up the regular match String AND a UTF-16 version
let matchString: String = "This is the text to search with the Regular Expression pattern."
let matchStringUTF16: String.UTF16View = matchString.utf16
// create your NSRegularExpression object
// get your match(es) - which are NSRange objects -
// and while looping through each:
// use the NSRange's location and length to create start and end values for the String Range
// (note: 'match' represents the current NSRange object; 'idx' is the current index of the loop)
let theNSRange: NSRange = match.rangeAtIndex(idx)
let nsRangeStart: Int = theNSRange.location
let nsRangeEnd: Int = theNSRange.location + theNSRange.length
// create UTF-16 start and end indexes using the UTFView version of the original String
let utf16StartIndex: String.UTF16View.Index = matchString16.startIndex.advancedBy(nsRangeStart)
let utf16EndIndex: String.UTF16View.Index = matchString16.startIndex.advancedBy(nsRangeEnd)
// use samePositionIn(String) to convert the UTFView indexes to regular CharacterView indexes
// note: these are optionals as the conversion may not work; handle appropriately in your own code
let stringStartIndex: String.CharacterView.Index? = utf16RangeStart.samePositionIn(matchString)
let stringEndIndex: String.CharacterView.Index? = utf16RangeEnd.samePositionIn(matchString)
// now, create a Range object with those CharacterView indexes
// FYI: Range<Index>, as seen in error messages, is short-hand for Range<String.CharacterView.Index>
let stringRange: Range<String.CharacterView.Index> = stringStartIndex!..<stringEndIndex!
// and prove it works by using the new Range on the original String to get the match's substring
let substringMatch: String = matchString.substringWithRange(stringRange)

Here are the details:
One example NSRegularExpression object method call looks like this:

func matchesInString(_ string: String,
options options: NSMatchingOptions,
range range: NSRange) -> [NSTextCheckingResult]

It requires a String for matching, but an NSRange for the part of the string to search. To convert TO an NSRange, you need to convert your regular String into an NSString to get the length - this part's easy:

// we're assuming we want to search the entire string
let nsMatchString: NSString = matchString as NSString
let nsRange: NSRange = NSMakeRange(0, nsMatchString.length)

Ah, but WHY? Why didn't we just use matchString.characters.count?

A Story of Character Encoding
Well, it turns out that OS X and iOS use an underlying character encoding called Unicode. Unicode utilizes "code units" to make up strings. And, the number of code units representing a given character will differ depending on how the character is represented in the UTF standard.

NSString uses a UTF-16 representation for working with Unicode characters. While many characters consist of only one code unit in UTF-16 form, some characters consist of more than one code unit. A letter "A", for example takes only one code unit. But, the emoji {Smiling face}, "☺️", consists of 2 code units in UTF-16 (and therefore also NSString).

Swift's String, on the other hand, uses a visible character count rather than calculating the underlying code units. So, the String literals "ABC" and "A☺️C" both seem to be 3 characters long: "ABC".characters.count and "A☺️C".characters.count both return 3.

But, when you convert those same strings to NSString, you get a little surprise: ("ABC" as NSString).length returns the 3 you'd expect. ("A☺️C" as NSString).length, though, returns 4! Yike!

Of course, the difference is because NSString is taking into account that extra UTF-16 code unit that String ignores.

Okay, now what about those ranges?
Swift bridges the String you provide to the function into an NSString object. So, the NSRange results you get back from the call are based on that UTF-16 length, not the actual String character count. If you've got any multi-code-unit characters in your String, the ranges you get back won't match up.

Additionally, NSRange objects provide a location and a length. These are both Int values, which won't work in a Swift Range. You need Index objects for the start and end of a Range object.

Speaking of indexes, Swift Range objects expect a particular type of Index. You've seen the error messages about Range<Index> or Range<String.Index>. These actually represent Range<String.CharacterView.Index>. So, you need to make sure you're using the right type of Index, or your conversion won't work.

The workaround!
Note: in the example code below, I haven't provided any error handling. Make sure to add code to handle any potential optional results, such as in creating your NSRegularExpression object. Guard statements come in handy here.

Now, here we go...
1) Swift has some UTF-16 representations for a String object. So, first, we'll ensure we've got a UTF-16 version of our match string. We'll use the utf16 property of String to convert our match string into its equivalent String.UTF16View type as well:

// set up the regular match String AND a UTF-16 version
//let matchString: String = "ABCABC" // switch the remarked string to experiment
let matchString: String = "A😏CA😏C"
let matchStringUTF16: String.UTF16View = matchString.utf16

2) We then set up our NSRegularExpression object.

//let regexPattern: String = "A(BC)+" // again, switch remarked strings to experiment
let regexPattern = "A(😏C)+"
let options = NSRegularExpressionOptions.CaseInsensitive
guard let regex = try? NSRegularExpression(pattern: regexPattern, options: options) else {
return
}

3) Then, we make our call to the regex object's appropriate function using the String value and the NSRange based on the NSString representation.

Note: strangely, the UTF16View version of the match string won't work for creating the NSRange. You MUST use an NSString cast to create the NSRange.

// creating the NSRange object to send into the function call
let nsMatchString: NSString = matchString as NSString
let nsRange: NSRange = NSMakeRange(0, nsMatchString.length)
// function call with original String and our new NSRange
let matches: NSTextCheckingResult? = regex?.matchesInString(matchString, options: matchingOptions, range: nsRange)

4) You'll need to loop through the results, converting as you go:

for (idx, matchItem) in matches.enumerate() {
let numMatches = matchItem.numberOfRanges
// now THIS gives us the NSRange for the main match PLUS each of the group captures
// rangeAtIndex(0) = main match (same object as matchItem[idx].range)
// rangeAtIndex(>0) = group capture match
for matchIdx in 0..<numMatches {
// use the NSRange's location and length to create start and end values for the String Range
// (note: 'match' represents the current NSRange object; 'idx' is the current index of the loop)
let theNSRange: NSRange = match.rangeAtIndex(idx)
let nsRangeStart: Int = theNSRange.location
let nsRangeEnd: Int = theNSRange.location + theNSRange.length
// then, using the UTF16View string, get the start and end UTF16 index types
let utf16StartIndex: String.UTF16View.Index = matchString16.startIndex.advancedBy(locationNS)
let utf16EndIndex: String.UTF16View.Index = matchString16.startIndex.advancedBy(locationNS + lengthNS)
// using the String.UTF16View.Index type's samePositionIn(String) function,
// you can finally get the String.CharacterView.Index types needed for the Range<String.Index>
let stringStartIndex: String.CharacterView.Index? = utf16StartIndex.samePositionIn(matchString)
let stringEndIndex: String.CharacterView.Index? = utf16EndIndex.samePositionIn(matchString)
// create your Range
let stringRange: Range<String.CharacterView.Index> = stringStartIndex!..<stringEndIndex!
// and use it against the original String to get your matching String - PHEW! All done!
let substringMatch: String = matchString.substringWithRange(stringRange)
}
}

Friday, April 22, 2016

Variadic Parameters (or, what are those three dots after the parameter type?) (Swift 2.2)

Swift gives us a cool way to indicate a variable number of parameters of a specified type in a function signature. This is called "variadic parameters". The parameter list is automatically converted to an array under the hood.

Note: A variadic argument can consist of zero or more values. As a result, the array could be empty. Make sure to account for this in your code, if necessary!

Here's what it looks like:
func doSomethingWithTheseColors(colors: UIColor...) { 
    // treat the list of colors as an array, eg:
    for (theIndex, theColor) in colors.enumerate() {
        print("\(theIndex). \(theColor.description)")
    } 
}
This function can then be called like this:
doSomethingWithTheseColors()
or
doSomethingWithTheseColors(UIColor.redColor)
or
doSomethingWithTheseColors(UIColor.redColor, UIColor.greenColor, UIColor.blueColor) 
You can call the function with as many arguments as you want (of the specified type, of course) - or none at all.

Resource: The Swift Programming Language (Swift 2.2) -> Functions (See Variadic Parameters)

Thursday, April 14, 2016

Adventures installing GnuPG (GPG) on El Capitan (Mac OS X 10.11)

GitHub has announced that they'll start marking commits and tags signed with GPG (GnuGP) signatures with a Verified tag. Excited about the thought of verifying my identity as to adds and updates, I went straightforward to set this up!

Note: a Mac binary (DMG) exists for setting up a suite of GnuGP tools: GPGTools
Also, a Mac binary exists for the "modern" version (meaning the up and coming, not yet stable version): GnuGP for OSX

I recommend one of these if you want a quick, easy setup on your Mac. However, I have to do things the hard way (mocking grin here ;)

Seriously,
- I only wanted the encryption/signing capability, as opposed to the whole email thing (GPGTools), and
- the GPGTools site was last updated in November of 2015 and indicated their El Capitan version was still in beta, while the GnuGP for OSX was the newest, not-"stable" version, and
- REALLY, I like to learn new things and understand how the underpinnings work. This was a chance for me to try "make"ing something from source on my Mac beyond simple C programs. I've generally used various tools that handle that stuff under the hood, so I thought this should be interesting.

Following the instructions here, then, I began the install process.

Long story short, including lessons learned:
  1. Download the following from the GnuPG Download page:
    • GnuPG stable
    • Libgpg-error
    • Libgcrypt
    • Libksba
    • Libassuan
    • Pinentry
  2. Download Gnu Portable Threads (Gnu pth). (Note: there may be newer versions of this or alternate configurations. I used v2.0.7 as linked on the page.)
  3. Verify each package's authenticity (please, no discussions of trust here! It is what it is.)
    • For Mac, use 'openssl sha1' to verify that the signatures match.
    • Text signatures for the GnuPG-listed packages are on at: GnuPG Integrity Check.
    • Gnu pth provides a .sig file for verification. To use this, you must already have a prior version of GnuPG installed. Alternatively, I found a matching SHA1 hash at the Free Software Foundation's membercard page for pth-2.0.7-14:  9a71915c89ff2414de69fe104ae1016d513afeee
  4. Uncompress all of the packages.
  5. Saving GnuPG itself for last, run these commands in Terminal from each package's own folder:
    • ./configure
    • make
    • sudo make install

Following these steps, the error you're most likely to find on a Mac has to do with unknown type names (intmax_t and uintmax_t). This error and the fix I chose, for right or wrong, is described in the long story below.

Once installed, follow the steps at GitHub Help for GPG to set up your account to use verification.

Setting up for GitHub, I discovered a few more things to note:
- If you're using a private email for GitHub, set up your GPG key with that email, not your "real" one.
- If your GPG installation uses the 'gpg2' command instead of just 'gpg', see the fix described in Edit 1, below.
- If your 'pinentry-agent' gives you grief about an 'inappropriate ioctrl', see the fix in Edit 2, below.


The long story:

I started by downloading GnuPG stable and verifying its authenticity:
- run the following command in Terminal to verify the signature:
openssl sha1 path/to/downloaded/file

- then compare the text signature from the GnuPG Integrity Check page with the result.

I then double-clicked the compressed file to break out the enclosed folder,

In Terminal, I cd'd (is that a word?) to the folder (gnupg-2.0.30 in my case) and typed the command ./configure (note: this is dot slash configure). The end output was a list of four dependencies I needed to install: libgpg-error, libgcrypt, libassuan, and gnu-pth.

Starting with Gnu Portable Threads (pth) (the messages said to install that one first!), I followed these steps for each dependency:
- Download the compressed file
- Locate and match a text version of the appropriate signature (using openssl as above)
- Uncompress the file (double-click in Finder)
- cd to the resulting folder, and
- run the following commands:

  1. ./configure
  2. make
  3. sudo make install

Note: no dependencies for 'libkbsa' or 'pinentry' showed up on the original ./configure list. However, I recommend you install those here as well in order to avoid pain later on ;)

Everything went smoothly, until I was ready to continue with GPG. I ran './configure' again, which appeared to complete with no problems. When I ran 'make', though... a bunch of errors came up having to do with 'intmax_t' and 'uintmax_t'.

intmax_t/uintmax_t errors:

The error messages looked like this, with a few pointing to 'uintmax_t' as well:

/usr/include/inttypes.h:235:8: error: unknown type name 'intmax_t'
extern intmax_t
       ^                                                                                                   

So, I went a'hunting. I found several resources which helped me locate and fix the problem, enabling me to complete the installation.

If you've worked with C, Objective-C, or C++, you know that you have to "include" header files for various reasons. Of course, you don't want to duplicate header file inclusions - and, you don't generally need to do so. Once you have included a header in one file, if you include that file in another file, the original header comes along for the ride.

Well, the problem here is that GnuPG has files designed to work on multiple systems, without knowing exactly what those systems will look like. And, apparently, the GnuPG developers generally work with Linux - not Mac. So, they do their best to code stuff that'll work on the Mac, but... well, there's reason they point you to the Mac-related GPG sites listed at the beginning of this article.

Getting to the point, a Mac with Xcode installed has two 'stdint.h' files and two 'inttypes.h' files. To further the complication, GnuPG has some 'stdint.h' files of its own.

Xcode's package contents contain a 'stdint.h' file. This file uses a typedef statement to define the constants 'intmax_t' and 'uintmax_t'.

Xcode's package contents also contain an 'inttypes.h' file. This file has no reference to either 'stdint.h' or 'intmax_t'/'uintmax_t'. However, it does have a reference to another 'inttypes.h' file, via a #include_next statement.

Now, #include_next means that the next file of the specified name found in the header search path should be included. Yike! Who knows where that could be (from strictly a file perspective, anyway) if someone might've changed up the search path?! Wow!

In this case, it appears that the next 'inttypes.h' file is in the /usr/include/ directory. At least, that's the file that's giving us those "unknown type name" errors.

The weird thing is that the /usr/include/inttypes.h file does #include a 'stdint.h' header. Theoretically, that header should contain the 'intmax_t' and 'uintmax_t' definitions.

We know that Xcode's package contents version has a typedef statement to handle that, so I checked the /usr/include/stdint.h: it has a #include <_types/_intmax_t> statement, as well as a corresponding statement for 'uintmax_t'. So, that 'stdint.h' should work, too. However, the /usr/include/inttypes.h file doesn't seem to be using either of those 'stdint.h' files. So, what 'stdint.h' is actually getting included?

It turns out that GnuPG has a 'stdint.h' file in the 'gl' directory that is causing - or related to, anyway - the problem. To fix the issue, locate that gl/stdint.h file under your GnuPG stable's folder.

Open the gl/stdint.h file in an editor (I suggest making a backup copy first, of course!), and look for this line:

# include "///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/include/stdint.h"

Remark out that line (put /* */ type comment marks around it) or delete it, and replace it with:

# include "///usr/include/stdint.h"

Now, try your 'make' command again. This time, assuming no missing files (such as libkbsa or pinentry), everything should work!

Continue with the 'sudo make install' command, and you should be ready to go!

Note: most of the GnuPG documentation uses the command as 'gpg'. For the version I used (2.0.7), the command is actually 'gpg2'. In this case, you may need to make various tweaks to get the GPG to run correctly with whatever application you're using. I'll leave that research up to you.

Enjoy your new certificate/key signing capabilities!


Edit 1:
When I tried to use my GnuPG (v2.0.7) with Git, I found Git didn't like the 'gpg2' command. Per a Stack Overflow answer provided by Jens Erat, I was able to use the following command to fix this issue:

git config --global gpg.program gpg2


Edit 2:
When I tried to perform a secure commit in Git, I got an error from the gpg-agent: inappropriate ioctl for device. Pinentry needs access to the Terminal window in order to allow you to enter the passphrase for your commit key. This error means that pinentry can't access the Terminal window correctly.

To fix this, create a .bash_profile file under your user's home (~) folder. (Note that the filename starts with a dot.) Add two lines to this file:

export GPG_TTY=$(tty)
export PINENTRY_USER_DATA="USE_CURSES=1"

Save the file, then restart your Terminal session.

To check if the change is in effect, run the 'set' command at the Terminal prompt. In the list of environment variables this command returns, look for entries for GPG_TTY and PINENTRY_USER_DATA. Ensure their values appear correct: the 'tty' value from the profile will be replaced by a default Mac value, while the pinentry value will show as expected.

Now, you'll be prompted for the passphrase so your commit will be signed properly.

Again, I am using OS X 10.11 El Capitan. This, or some similar setup, may work in other versions of OS X and on Linux, based on my research, but tread on at your own risk. Also, I'm using the default Bash shell.












Friday, March 25, 2016

Even more easily use a Navigation Bar without a corresponding Navigation Controller!

Well, so I wrote up this set of steps to add a navigation bar independent of a navigation controller:
Easily use a Navigation Bar without a corresponding Navigation Controller

Only to find that there's an even EASIER way!

Posted by joerick on Stack Overflow, you can do this in 3 steps - completely within the storyboard:

1) Add your navigation bar.

2) Add your constraints:
  • Navigation Bar.Top = Top Layout Guide.Bottom
  • Navigation Bar.Leading = Superview.Leading
  • Navigation Bar.Trailing = Superview.Trailing

3) In the Identity Inspector for the bar, add a user defined attribute:
  • Key Path: barPosition
  • Type: Number
  • Value: 3

That's it!

Many thanks to joerick! If this helps you, give 'em a vote up:
ios - Is there a way to change the height of a UINavigationBar in Storyboard without using a UINavigationController? - Stack Overflow


Again, here are some GIFs to show you the details:

1) Add your navigation bar. Just center it and click it to the guide. Don't worry about the weird space at the top.





2) Set the constraints for the navigation bar in the storyboard. All should have a constant of zero and a multiplier of one. Note: Ctrl-click to connect the navigation bar with the view in the outline; shift-click to select multiple items in the list:
    - Navigation Bar.Top = Top Layout Guide.Bottom
    - Navigation Bar.Leading = Superview.Leading
    - Navigation Bar.Trailing = Superview.Trailing




3) In the Identity Inspector for the bar, add a user defined attribute for barPosition, give it a type of Number, and give it a value of 3.






4) As you can see, you still get the same result - a normal, autoresizing navigation bar!







Thursday, March 24, 2016

Easily use a Navigation Bar without a corresponding Navigation Controller

Recently I had to wrangle with an independent navigation bar, without a corresponding navigation controller. My challenge was to get the bar to resize appropriately, as it would normally do if it had a navigation controller - and do it primarily via the storyboard.

It turned out to be surprisingly easy!

Here's the short version:
1) Add the navigation bar to the view controller in the storyboard.

2) Set the constraints for the navigation bar in the storyboard:
    - Navigation Bar.Top = Top Layout Guide.Bottom
    - Navigation Bar.Leading = Superview.Leading
    - Navigation Bar.Trailing = Superview.Trailing

3) Connect the storyboard's navigation bar to its view controller as an @IBOutlet.

4) In the view controller's class, add a UINavigationBarDelegate protocol to the class declaration.

5) In the view controller's viewDidLoad method, set the navigation bar's delegate to self.

6) In the view controller, add the bar positioning delegate's positionForBar method. Return the UIBarPosition representing TopAttached. (Note: UINavigationBarDelegate inherits this method from UIBarPositioningDelegate.)

That's it! Now your navigation bar will autoresize as though it were being controlled by an actual navigation controller - without the navigation controller!

Here's the long story:
1) Add the navigation bar to the view controller in the storyboard. Note that the navigation bar doesn't go all the way to the top! Line it up below the battery icon, where the guide "snaps" it in. This looks weird, but trust me, this'll work fine by the time we're done.


















2) Set the constraints for the navigation bar in the storyboard. Note: Ctrl-click to connect the navigation bar with the view in the outline; shift-click to select multiple items in the list:
    - Navigation Bar.Top = Top Layout Guide.Bottom
    - Navigation Bar.Leading = Superview.Leading
    - Navigation Bar.Trailing = Superview.Trailing




3) Connect the storyboard's navigation bar to its view controller as an @IBOutlet.

























4) In the view controller's class, add a UINavigationBarDelegate protocol to the class declaration. (Note: this protocol inherits from the UIBarPositioningDelegate protocol, allowing us to use the positionBar method in step 6, below.)









5) In the view controller's viewDidLoad method, set the navigation bar's delegate to self. (Note: we can do this since we set the view controller up as a UINavigationBarDelegate in step 4, above.)




6) In the view controller, add the bar positioning delegate's positionForBar method. Return the UIBarPosition representing TopAttached.  (Note: as mentioned in step 4, above, this method is available to our view controller because UINavigationBarDelegate inherits from UIBarPositioningDelegate.)




7) Try flipping back and forth in the simulator (or on a phone)! Notice how the navigation bar is correctly resized and positioned - without any further action on your part!

Thursday, March 17, 2016

Segue Unwind to One of Two View Controllers (Swift 2.1)

Situation: I have a table view and a collection view. Both can go to the same view controller for editing an item. Now, how to get back to the correct starting view?

Resources I used:
Technical Note TN2298: Using Unwind Segues
Specifying the Destination of an Unwind Segue Programmatically
View Controller Programming Guide for iPhoneOS: UsingSegues

How I did it:
- Add an instance variable to both the table and collection view controllers. We'll use this to tell whether the containing controller started the segue. Default it to false, of course.
var startedEditorSegue = false

- Override the prepareForSegue function for both view controllers. Here, we'll set the startedEditorSegue variable to true, since we're starting the segue from the specified controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let segueId = segue.identifier else {
return
}
switch segueId {
case "tableViewSegueToEditor":
  // this controller is starting a segue to the editor, so unwind needs to return here
startedEditorSegue = true
default:
print("not editor segue")
}
}

Note: I don't have any untitled segues that should be coming through, so I used a guard statement. If you have untitled segues, you may want to use conditional unwrapping (if let segueId = segue.identifier...) or something else instead.


- Override each of the controller's canPerformUnwindSegueAction functions. If the controller started the segue, it will return true due to prepareForSegue code above. If not, the controller will return false.
override func canPerformUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject) -> Bool {
 // if we started the segue, then we can handle it; otherwise, pass
return startedEditorSegue
}
Note: if you need to do multiple unwind actions, you can check which one is occurring via the action parameter. In this case, the parameter will contain my custom selector: unwindFromEditor:


- Create a custom unwind function with the same name in both the table and collection view controllers. Here, we'll reset the startedEditorSegue to false, so it'll be ready for the next round.
@IBAction func unwindFromEditor(segue: UIStoryboardSegue) {

 // the editor's unwind came here; all we need do is revert the indicator
 // to false, so it's valid for the next unwind action
startedEditorSegue = false
}
Note:
* This action doesn't get "connected" to anything, but must be an @IBAction anyway.
* The name of the function can be anything you want.
* The function must have one parameter of type UIStoryboardSegue.


- In the storyboard, CTRL-drag from the editor view controller's button to initiate the segue to the same view controller's exit icon. You'll get a menu with your custom-named unwind action.



Select the action - and you're done!

Now, when the appropriate button is pressed, the unwind segue will traverse your view hierarchy. It'll ask each view whether it can respond to the unwind. Due to the canPerformUnwindSegue function in conjunction with the startedEditorSegue variable, the table and collection view will respond appropriately, and the process will return to the right place.

On a side note: you can give the segue an identifier: select the segue in the Storyboard's document outline, and open its Attributes Inspector.

Happy coding!



Tuesday, March 8, 2016

Dang those broken constraints (because of the status bar!)

I keep looking this up, so here I'm putting it for posterity:

This Xcode error:

<NSLayoutConstraint:0x134682ba0 'UIInputWindowController-top' V:|-(0)-[UIInputSetContainerView:0x13468f180]   (Names: '|':UITextEffectsWindow:0x13468df70 )>"
Means:
    NOTHING! Well, actually, it means simply that the status bar is not in its normal state.

Explanation:
    In certain cases, your iPhone's status bar will be extended. For example, if you're in a call and navigate out of the main call window, a green bar representing the call will appear above the normal status bar area. Another example: if you're using the Personal Hotspot on your iPhone, a blue bar showing the connection status appears above the normal status bar area.

    If you're testing an app while this extended status bar is present, you will get the crazy NSLayoutConstraint/UIInputWindowController-top/UIInputSetContainerView/UITextEffectsWindow error message.

That's all it is, folks! Nothing to worry about at all!