Where technology meets something or other


Erica Sadun. iPhone. iPod touch. Macintosh. and More.

Contact

erica at ericasadun.com

Meta

  1. RSS
  2. admin
  3. valid XHTML

Folderol FAQ #3: Avoiding color blending0 Comments

erica | 9:29 am | February 1, 2015 | Admin,FAQ,Software

Kent writes:

Just purchased folderol (v 1.9). I’m having a dilemma when adding custom images. Sometimes it blends the custom image into the blue color of the folder which changes the color of the image. Other times it doesn’t. I’d like to say I’ve figured out a pattern but I haven’t.

Answer:

I’m going to take a guess that you have chosen a color while adding a custom image. The active color is always blended to the image unless you choose to remove the active color. Once you clear the color, you’ll see a checked board background. Now when you add a custom image and drop a folder, the image will not blend with a hue.

Screen Shot 2015-02-01 at 09.09.56

Image 2-1-15 at 9.13 AM

There’s also a further option called Don’t blend image to icon. When you enable this, the image will replace the folder instead of blend with it.

Here’s what all these options look like:

Original folder: 

Screen Shot 2015-02-01 at 9.21.28 AM

Blended with image (normal, no tint selected)

Screen Shot 2015-02-01 at 9.24.26 AM

Blended with image (pink/red tint selected)

Screen Shot 2015-02-01 at 9.25.31 AM

Do not blend option enabled (no blend with original folder art or the folder’s blue tint)

Screen Shot 2015-02-01 at 9.27.11 AM

 


Swift: Fun with Ranges1 Comment

erica | 8:55 am | January 22, 2015 | Development,Swift

Screen Shot 2015-01-22 at 8.47.26 AM

Update: Easy fix from Joachim and Jacob, proving that my brain is fried. Joachim notes: ” Range and Interval have been separated into separate classes during the beta. … Creates either depending on context.”

I’ve been playing recently with custom operators. The operator grammar in the Swift Programming Language is a bit obtuse as it lists ranges of unicode characters instead of just showing you a table of what the legal ones are. (There are a lot.) So I hopped into a playground hoping to iterate through them to see if any nice/intriguing/helpful characters popped up. What followed was an interesting exploration of arrays of ranges.

I started by creating a basic list of items I wanted to look at, using the list of “operator-head”-compatible hex values.

var ranges : [Range<Int>] = [
    0xA1...0xA7,
    0xA9...0xA9,
    0xAB...0xAB,
    0xAC...0xAC,
    0xB0...0xB1,
    0xB6...0xB6,
    0xBB...0xBB,
    0xBF...0xBF,
    0xD7...0xD7,
    0xF7...0xF7,
    0x2016...0x2017,
    0x2020...0x2027,
    0x2030...0x203E,
    0x2041...0x2053,
    0x2055...0x205E,
    0x2190...0x23FF,
    0x2500...0x2775,
    0x2794...0x2BFF,
    0x2E00...0x2E7F,
    0x3001...0x3003,
    0x3008...0x3030,
]

But when I attempted to iterate, I ran into errors that ClosedInterval<Int> items do not conform to SequenceType protocols:

for range in ranges {
    for item in range {
        var unicode = String(UnicodeScalar(item))
        println(String(format:"0x%X: \(unicode)", item))
    }
}

Instead, I had to create a new range out of the interval as follows:

for range : ClosedInterval<Int> in ranges {
    for item in range.start...range.end range {
        var unicode = String(UnicodeScalar(item))
        println(String(format:"0x%X: \(unicode)", item))
    }
}

Thanks Joachim and Jacob for fixes.

I think my brain is too dead this morning to really think about this in depth but it seems to me a bit odd that I had to work around this in this way, since a closed interval is intrinsically range-y. (Update: Fixed.)

Most of the operator-ready characters by the way are pretty meh but that’s an entirely different post.

 


Converting the Swift Programming Language to PDF2 Comments

erica | 11:57 am | January 8, 2015 | Development,Swift,Various Frustrations

Screen Shot 2015-01-08 at 11.52.19 AM

I hate that Apple has more or less stopped its practice of including PDF links in its reference library online docs. I hate even more that I don’t have a PDF version of the Swift Programming Language to search through and mark up using Preview. (I don’t really like the iBooks interface.)

Today, I spent a while googling and figuring this out so you don’t have to.

  1. Find the epub. Easiest way to do this is to delete your copy from iBooks and re-download. Then hop over to ~/Library/Containers/com.apple.BKAgentService/Data/Documents/iBooks/Books and sort by date modified.
  2. Adjust the epub to something Calibre can read. Let me save you a lot of time. The .epub in the Books folder is actually a folder itself, and not a renamed zip file per standards. So create a zip file (zip out.zip -r 881256329.epub), rename it from zip to epub, and throw it into Calibre.
  3. Convert with Calibre. Start here. Add the new epub and convert it to a PDF destination. I used the default settings. When the conversion job finishes, open in Preview.

As you see, there’s really not that much involved. It was the time figuring out why the epub wouldn’t open that really drained my morning.


Folderol and Yosemite1 Comment

erica | 10:04 am | October 20, 2014 | Admin,OS X,Various Frustrations

Screen Shot 2014-10-20 at 9.42.53 AM

A last second (very last second) Yosemite API change is fixed and a new version of Folderol is awaiting review at iTunes Connect. I apologize for the inconvenience. Email me if you need a beta version to hold you through until the fix is approved.


Size dumps2 Comments

erica | 2:44 pm | September 15, 2014 | Development,iOS,Xcode

Make of this what you will. I’ve interspersed updates into everything that follows.

When I ran my older apps, everything ran at 320×568 on the new devices. To get the following numbers, I created entirely new projects. (Saniul Ahmed tweeted me that you need to provide current launch images to get the new dimensions.) Lesson: Update your launch images or create new projects to take full advantage of the new dimensions.

From the docs: “The iPhone 6 Plus uses a new Retina HD display with a screen scale of 3.0. To provide the best possible experience on these devices, include new artwork designed for this screen scale. In Xcode 6, asset catalogs can include images at 1x, 2x, and 3x sizes; simply add the new image assets and iOS will choose the correct assets when running on an iPhone 6 Plus. The image loading behavior in iOS also recognizes an @3x suffix.” So the 6 Plus is 3x. Right. (Even though it’s reporting oddly  in the below info dump.)

Compare and contrast with the marketing text: “The size of the new, higher-resolution Retina HD displays on iPhone 6 and iPhone 6 Plus may be the first thing you notice.” (The same  HD mention is here as well.) But the 6 non-plus is reporting correctly for @2x ,not @3x, so I suspect the marketing text is wrong. (Thanks akempgen)

Lesson: The 6 plus uses a 3x scale. The 6 does not. Retina HD seems to mean something different between marketing text (high density) and developer docs (3x resolution).

More explanation about iPhone 6 screens from the guys at PaintCode. Read about it here. Lesson: This new stuff is strange.

With no further ado, here are my original tests.

Testing iPhone 6 plus
iPhone Simulator
iPhone OS
8.0
iPhone Simulator
<UIView: 0x7f854596f7a0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x7f854596bd50>>
<UIWindow: 0x7f854596e1e0; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x7f854596edd0>; layer = <UIWindowLayer: 0x7f854596c0d0>>

Testing iPhone 6
iPhone Simulator
iPhone OS
8.0
iPhone Simulator
<UIView: 0x7ffb11415b80; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7ffb11402be0>>
<UIWindow: 0x7ffb14113000; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7ffb14113a20>; layer = <UIWindowLayer: 0x7ffb1410f410>>

Testing iPhone 5s
iPhone Simulator
iPhone OS
8.0
iPhone Simulator
<UIView: 0x7fcb21d13d90; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7fcb21d13090>>
<UIWindow: 0x7fcb21d10e70; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x7fcb21d11770>; layer = <UIWindowLayer: 0x7fcb21d0d140>>

Testing iPhone 5
iPhone Simulator
iPhone OS
8.0
iPhone Simulator
<UIView: 0x7a0d6a50; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7a0d6310>>
<UIWindow: 0x7a17a5c0; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x7a17ac00>; layer = <UIWindowLayer: 0x7a17a550>>

Testing iPhone 4s
iPhone Simulator
iPhone OS
8.0
iPhone Simulator
<UIView: 0x7ae9a000; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x7ae9c730>>
<UIWindow: 0x7ae9c600; frame = (0 0; 320 480); gestureRecognizers = <NSArray: 0x7ae9cb20>; layer = <UIWindowLayer: 0x7ae9c210>>

Anyway, this was what I tested out:
Screen Shot 2014-09-15 at 2.54.04 PM


Swift: Command-line basics2 Comments

erica | 1:55 pm | August 29, 2014 | Development,Swift

Just because someone wandered along today asking about input from stdin. No guarantees about edge conditions.

import Foundation
import Darwin

var myString : UnsafeMutablePointer<Int8> = UnsafeMutablePointer.alloc(100)
println("Enter your name")
fgets(myString, 100, stdin)
let myName = String.fromCString(myString)
println("Hi \(myName!)")

Auto Layout: iOS 83 Comments

erica | 1:34 pm | August 28, 2014 | Development,iOS,OS X,Various Frustrations,Xcode

It’s been a pretty exciting summer as far as Auto Layout goes. I’m busy going over material so I can get some dates and work estimates to Trina on a possible 3rd edition of Auto Layout. Between Swift, OSX, iOS 8, and whatever is going to be announced in September, it looks like a particularly interesting place to be.

I can’t tell you how thrilled I am about active, the property that self-installs and removes constraints to their natural destination. I submitted my first radar on this back before the first edition was even published. Now with the third edition, I suppose I’ll be all “Yeah, that’s my radar baby!”

The long iOS 8 summer first gave us left and right layout guides, a la the top and bottom guides we first encountered in iOS 7 but they soon disappeared and have since been replaced by a suite of Margin-based layout attributes:

    NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),

Comments and properties in the UIView header file indicate a layout tree of margins. I think it’s fair to assume this ties into the adaptive application that runs properly both on full-screen as well as side-by-side.

/*
 -layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
 If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the left edge of their superview's bounds
 If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your view if the margins change.
 */
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); // default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);

Unfortunately, the material from WWDC is light on details and these updates didn’t take place until fairly recent betas. Got any insights into how this material will play out? I’d love to hear it. (And thanks in advance!)


Swift: Embettering solutions2 Comments

erica | 12:00 pm | August 27, 2014 | Development,Swift

With Swift, there’s almost always a better way to do things and when you get to that better way, it just rings with “of course”-ness.

As usual, this started as a question from a participant in #swift-dev. “This doesn’t work,” he said, and pasted the following.

func continueGame() {
    if self.gameLogic.count == 0 {
        return
    }
    self.gameLogic[0]()
    self.gameLogic.removeAtIndex(0)
}

So I started kicking the wheels on it. To get going, I decided to use the following array of closures to test my approaches.

[Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]

First, I explained about using a generator and the next() function:

var myarray : [Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]
var mygenerator = myarray.generate()

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

That wasn’t practical for a generalized implementation.So I built a few loops that eventually ended up like this:

while true {
    if let closure = mygenerator.next() {
        closure()
    } else {
        break
    }
}

But Ken Ferry took one look at that, laughed, and suggested the following (far more elegant) solution instead:

while let closure = mygenerator.next() {closure()}

Beautiful and simple. Thanks, Ken.


Swift: Converting values to enumerations2 Comments

erica | 8:14 am | | Development,Swift

Yesterday in #swift-lang, an enumeration discussion buzzed. A chat participant asked, “Is there any way to go backwards in an enum? I want to look up an enum based on a value.” The answer is simple and accessible. Creating enumerations from values returned by services and function represents an important touchpoint in Swift development.

RawRepresentable

The RawRepresentable protocol consists of two underlying functions: toRaw() and fromRaw(). These enable you to transform enumerations to and from underlying data states.

protocol RawRepresentable {
    typealias Raw
    class func fromRaw(raw: Raw) -> Self?
    func toRaw() -> Raw
}

For example, if you base your enumeration on integers, you can use the underlying sequence to move to and from that representation.

enum Nums : Int { 
    case Zero
    case One
    case Two
    case Three
}

var z : Nums = Nums.fromRaw(2)!
z == .Two // true
z == .Three // false

This example uses an Int raw-value type for its underlying representation. The type appears just after the name of the enumeration.

Fun with Raw Values

The enumeration values do not have to exactly match 0, 1, 2, etc. For example, you might assign arbitrary values to the enumeration entries.

enum Nums : Int {
    case Zero = 5
    case One = 30
    case Two = 15
    case Three = 20
}

var z : Nums = Nums.fromRaw(20)!
z == .Two // false
z == .Three // true
println(Nums.Three.toRaw()) // prints 20

Nor are your raw-convertible enumerations limited to integers. You have access to any equatable literal, specifically integer literals, floating-point literals, string literals, booleans, and nil. For example, you might use strings as raw values:

enum Lets : String {
    case X = "x"
    case Y = "y"
    case Z = "z"
}

var zz = Lets.fromRaw("z")
zz! == .Z // true
println(Lets.Y.toRaw())

Each case must declare a unique name and value. If you skip the value for integers, as in the first example in this post, they implicitly inherit their order. The count starts at zero and increases monotonically from there.

Raw vs Associated Values

Don’t confuse raw values with associated values. A raw value is constant across all uses of an enumeration. They are defined in the enumeration declaration at compile time. Associated values enable you to store typed information in an enumeration. These are defined at runtime.

enum CocoaResult {
    case success(NSObject) // associated success value
    case failure(NSError) // associated error value
}

Swift: Capturing references in closures1 Comment

erica | 9:10 am | August 26, 2014 | Development,Swift

Consider the following code snippet. It creates a closure that prints out the value of the variable i. When it runs, should it print out 25, the value of the variable at the time the closure was created, or 35, the current contents of the memory pointed to by the variable reference?

var i = 25
var cl = {println(i)}
i = 35
cl()

If you paste this snippet into a playground, you’ll find that this code prints 35, and not 25. That’s because Swift closures default to capturing references, not values. To change this behavior and capture the value, use a capture list, as in the following example.

var i = 25
var cl = {[i] in println(i)}
i = 35
cl()

The use of [i] enables you to capture the value of i at the time you create the closure instead of at a later runtime.

Capture lists appear as the first item in a closure. They’re listed before any parameter clauses or identifier lists and require the in keyword to be used. For example, here’s another closure. This one is String -> Bool. It more or less does the same work as the previous closure but offers extra syntactic elements so you can see a capture list in a more complex setting.

var anotherClosure = {
    [i] (x : String) -> Bool in
    println(i)
    return true
}

Here’s another example, one that uses a class instance instead of an integer.

class MyClass {
var value = "InitialValue"
}

var instance = MyClass() // original assignment
var cl2 = {[instance] in println(instance.value)}
instance = MyClass() // updated assignment
instance.value = "UpdatedValue"
cl2()

If you omit the [instance] in capture list, this example prints out “UpdatedValue”, the value associated with the updated variable assignment. With the capture list, it prints “InitialValue”. This is the value stored by the original assignment.

When working with classes, a capture list can add modifiers to captured elements, specifically weak, unowned, unowned(safe) and unowned(unsafe). According to the reference material I’ve been reading, you most commonly see modifier usage when you want to capture self without reference cycles. The Swift Programming Language offers the following example. Here, the capture list enables you to capture the reference to self as an unowned — instead of strong — reference, avoiding reference cycles.

lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)"
        } else {
            return "<\(self.name) />"
        }
    }

Thanks Kevin B.


« Older Posts

wordpress | sheepdip design by mahud © 2007