Manbolo Blog

Manbolo Team Blog, creators of MeonArchives

Official Apple Swift Blog

Another proof that Apple is changing, this dedicated blog on Swift. Swift is in flux, and there are some important changes to the syntax before the official 1.0, so bookmark this official feed.

Already good advises in the second article on compatibility:

This means that frameworks need to be managed carefully. For instance, if your project uses frameworks to share code with an embedded extension, you will want to build the frameworks, app, and extensions together. It would be dangerous to rely upon binary frameworks that use Swift — especially from third parties. As Swift changes, those frameworks will be incompatible with the rest of your app. When the binary interface stabilizes in a year or two, the Swift runtime will become part of the host OS and this limitation will no longer exist.

Beware of this issue: while the binary interface is not frozen, all components of your app (especially Swift framework that you don’t have the source code) should be built with the same version of Xcode and the Swift compiler to ensure that they work together.

From jc.

Zen and the Art of the Objective-C Craftsmanship by Luca Bernardi and Alberto De Bortoli

The idea underneath is that the code should not only compile, instead it should "validate". Good code has several characteristics: should be concise, self-explanatory, well organized, well documented, well named, well designed and stand the test of time. The main goals behind the curtain are that clarity always wins over performance and a rationale for a choice should always be provided. Some topics discussed here are general and independent from the language even if everything is tied up to Objective-C.

Zen and the Art of the Objective-C Craftsmanship is really a good book on Objective-C guidelines. Cocoa is full of conventions: if you’re an experienced iOS or OSX developer, you’ll already know most of these best practices; but I bet you’ll also learn two or three things you didn’t know (great discussion on blocks and retain cycles on self).

Luca and Alberto started writing this book on November 2013. But now Swift is the future of Mac and iOS development so they decided to release the current version of their book. Great work (via Dave Verwer’s iOS Dev Weekly).

From jc.

Social Login Buttons Aren’t Worth It by MailChimp

Quite funny, we just have this discussion this morning: we ask ourself if one should propose a Facebook or Twitter login while designing a new login page. MailShimp in Social Login Buttons Aren’t Worth It gives some really good reasons (and analytics) not to use social login buttons:

Sometimes you log in with Twitter, sometimes with Facebook, sometimes with a username and password specific to that app. It’s hard enough to remember your username and password, let alone which service you should bloody use to log in. As you add login buttons to a page, you also add decision points for users, while creating visual complexity in your design. The marginal gains in login rate are chipped away by the additional cognitive load you’re adding for your users.
[…]
Is it worth it? Nope, it’s not to us.

From jc.

Apple on Hamburger Menus

Mike Stern, Apple User Experience Evangelist in Designing Intuitive User Experiences - 211 WWDC 2014 session (at 31’ 57"):

But I feel like I would be remiss If I didn’t use this opportunity to talk with you about hamburger menus. AKA Slide out menus, AKA sidebars, AKA basements, AKA drawers.

Now, these controls are very common on iOS, and on other platforms. And I’m sure many of you here work on apps that have these. You guys made the decision to put it in your app. And I’m sure that you did so with the very best of intentions. And I will say that these controls do a couple of things very well.

For one thing, they save space. So rather than taking up a bunch of room at the bottom of the screen for a tab, you’re just taking up a little bit of area in the top left corner for the hamburger menu.

And you practically have the entire height of the screen to show options to people, and if that’s not enough, you’re going to cram more awesomeness into your app, people can scroll, right.

But, this is - I actually haven’t played around with the latest version of Xcode, so I really hope that they haven’t changed this - I don’t believe you’ll find a hamburger menu controller inside of Xcode.

Now, typically we don’t provide design advice about the things that we don’t offer to you guys, but I can’t help myself, right? I’ve so many conversations with people about this control, spending hours and hours talking about it, and you know, I think it’s important that we talk about it here today.

And again, I’m not going to say that there’s no place for these controls categorically. I think there are some apps that could maybe use one. But I will say that their value is greatly over-stated, and they have huge usabiliy downsides too.

Remember, the three key things about an intuitive navigation system is that they tell you where you are, and they show you where else you can go. Hamburger menus are terrible at both of those things, because the menu is not on the screen. It’s not visible. Only the button to display the menu is.

And in practice, talking to developers, they found this out themselves. That people who use their app don’t switch to different sections very frequently when they use this menu. And the reason for that is because the people who use their app don’t know where else they can go. Right? They don’t know because they can’t see the options, or maybe they saw it at one point in time, but they have since forgotten.

And if you use this control, you have to recognize that the people who use your app may not realize the full potential of your app.

Hamburger menus are also just tedious, right? If you want to switch sections from the Accounts tab to the Transfers tab, all you need to do is tap the button and you’re there instantly, and if you want to go back, you tap the account button, and you’re back where you started from.

Doing the same thing with the hamburger menu involves opening the menu, waiting for the animation to finish, re-orienting yourself, finding the option you’re interested in, tapping that, and then waiting for the animation to complete, getting back to where you were before, and if you want to go back, you have to open the menu again, go through that whole process, and there you are, again.

It takes at least twice as many taps to change sections. Something that should be very easy and fluid is made more difficult.

And the other thing the hamburger menus quite frankly do badly is that they don’t play nicely with back buttons. Right? I’ve seen this a lot. Back buttons are supposed to go in that top left corner position, but instead there’s this hamburger menu there, so people put the back button right next to it, but no longer does this look like a back button anymore, it just looks like this arrow which is pointing to the hamburger menu, looks ridiculous, and sometimes people recognize that it looks ridiculous so when you drill down into the hirerarchy of an app, the hamburger menu goes away. Now it takes even more steps to switch to a different section. You have to go back up enough times to get to a level in the hierarchy of an app to get to a view that contains the hamburger menu.

Now, sometimes people will try to solve this by putting the menu on the right-hand side, but that’s not advisable either. That location is a really important location. Usually, you can put some kind of action there, you know, like a plus sign to add something, or an edit button.

And finally, the downside of being able to show a lot of options is that you can show a lot of options. Is that you will show a lot of options. The potential for bloat and misuse is tremendous. They allow you to add all sort of stuff that your users don’t really care about. Like information about the app. Or version history, or credits. I hate to break it to you, but no one cares.

And the other thing is that people wind up taking ads and special offers and making them look just like regular sections and putting it in there too. That sucks. No one wants that either. Look, drawers of any kind have a nasty tendency to fill with junk.

Okay, let’s move on. [ Applause ]

Apple could not be clearer: don’t use hamburgers menus on iOS.

From jc.

Why and How to Avoid Hamburger Menus by Luis Abreu

Luis Abreu on Why and How to avoid Hamburger Menus:

The Sidebar Menu pattern welcomes bad IA because you can simply add one more thing to it without a direct consequence — that is until people actually use it.

This is really my main grip against hamburger menus: with this slide menu, you’ve a place where you can cram any stuff you want instead of focusing on your main app features.

The opposite of design in fact (on iOS, I’ve never seen an Apple app using one).

Some goods links at the end of the article:

We now have data that suggests Sidebar menus—sometimes called Hamburger Menus/Basements—might be causing more harm than good.

From jc.

How to Remove Duplicates in Open With Dialog on OSX

Duplicate entries

The OSX "Open With" menu can sometimes be clustered with duplicates. To remove them, close all Finder windows, open a terminal and type:

/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

Done (works on Mavericks and +).

From jc.

Swift Year Zero

This has been the most important WWDC since the introduction of the iPhone SDK, 6 years ago.

On the really incredible amount of new features, for both developers and users, I will highlight two things:

1: App Extensions. Think of it as a mini version of your app that can be opened in the context of an another app. Today, in Safari, you can share links with Twitter and Facebook: when you share an URL, a small dialog appears, this is an extension of Twitter or Facebook, inside Safari. With iOS 8, any app can appear in this sharing menu and have a small interface inside Safari, to process the current web page. This is not limited to Safari, but in fact any apps can use extensions provided by your app. It’s really a secure and easy way to seamlessly share datas between apps.

I think that App Extensions will completely modify the way we use and develop apps, a lot of new features are now possible: we stand today on the edge of a New Frontier for iOS!

2 : Swift, of course. I really like Objective-C, the grammar is very small, and there has been a number of really good additions to streamline the development like ARC and Objects literals. Now, we have a brand new language, designed to be the iOS / OSX developers lingua franca for the next 10-15 years, and I’m a little scared! Swift looks modern and brilliant with function as first class citizens, a REPL, inferred type, a powerful case pattern matching, tupples etc… But it’s the unknown

We’re at the Year Zero of this new language and I’m a little afraid to leave behind me a really good friend.

And, of course, I’m also excited: it’s so good to be an iOS developer!

From jc.

Shell Scripting with Objective-C

Updated on 2014/06/09: Interesting discussion on Hacker News, with a bash and an Objective-Smalltalk alternative. The bash one is certainly the most concise.


Inspired by Nicolas Bouilleaud’s Objective-C Minimalism, I’ve tried to see if I could use Objective-C for shell scripting on my Mac. I normally code my shell scripts in Python, I love the language, so easy to read, so fun to write, with a ton of brillant third-party libraries, like Requests, Pillow or Beautiful Soup. But I would like to see if Objective-C could also do the job for shell scripting: as I spend the most of my day job writings iOS apps, I could maybe reuse my knowledge for small utility scripts.

The Challenge

Let’s take an example: I would like to get the app icons for a list of iOS apps available in the store. I need these icons in different sizes, let’s say 1024 pixels, 512 pixels, 120 pixels etc… and the icons should come with the new iOS 7 shape.

Getting an app icon from iTunes is really simple. The App Store has a lookup web API to query for all metadata of an app (title, description, icon, screenshots, ratings etc…). For instance, given an app id, we can ask for the metadata of Kingdom Rush Frontiers: http://itunes.apple.com/us/lookup?id=598581396

{
"resultCount": 1,
"results": [{
    "artistId": 558612918,
    "artistName": "Ironhide Game Studio",
    "artistViewUrl": "https://itunes.apple.com/us/artist/ironhide-game-studio/id558612918?uo=4",
    "artworkUrl100": "http://a680.phobos.apple.com/us/r30/Purple/v4/55/92/7d/55927d0d-bf19-dd3f-ff72-ff6069e7c7b5/mzl.sfsarfno.png",
    "artworkUrl512": "http://a680.phobos.apple.com/us/r30/Purple/v4/55/92/7d/55927d0d-bf19-dd3f-ff72-ff6069e7c7b5/mzl.sfsarfno.png",
    "artworkUrl60": "http://a407.phobos.apple.com/us/r30/Purple/v4/dc/4a/01/dc4a0174-dde5-65b0-f952-862c0ea1d070/Icon.png",
    "averageUserRating": 4.5,
    "averageUserRatingForCurrentVersion": 4.5,
    …

From the JSON result, we can see that the icon’s URL is http://a680.phobos.apple.com/us/r30/Purple/v4/55/92/7d/55927d0d-bf19-dd3f-ff72-ff6069e7c7b5/mzl.sfsarfno.png.

But the icon provided by the iTunes Lookup API is totally square, and doesn’t include the standard rounded iOS 7 shape. So, in our script, we’ll also apply a mask on the 1024 x 1024 icon, and compute all the resized icons with this mask.

In Python

This is the Python code:

#!/usr/bin/env python
from StringIO import StringIO
import requests
from PIL import Image
from slugify import slugify


def download_icon(icon_url, title, mask):
    """
    """
    # Download icon an apply mask.
    icon_data = requests.get(icon_url)
    icon = Image.open(StringIO(icon_data.content))
    icon.putalpha(mask)

    # Compute and save thumbnails.
    for size in [1024, 512, 120, 114, 60, 57]:
        icon_resized = icon.resize((size, size), Image.ANTIALIAS)
        icon_resized.save("icon_{0}_{1}x{1}.png".format(title, size))


def download_app_metadata(app_id, mask):
    """
    """
    print("download_app_json {}".format(app_id))

    url = "http://itunes.apple.com/us/lookup?id={}".format(app_id)
    r = requests.get(url)
    if r.status_code != 200:
        print(’Error downloading {} {}’.format(url, r.status_code))
        return

    results = r.json()

    meta = results["results"][0]
    icon_url = meta["artworkUrl512"]
    title = slugify(meta["trackCensoredName"])

    download_icon(icon_url, title, mask)


def download_icon_mask():
    """
    """
    # Download the mask from Dropbox, this way we don’t
    # have to provide mask.png and the script is self contained.
    mask_url = "https://raw.githubusercontent.com/manbolo/appicon/master/mask.png"
    mask_data = requests.get(mask_url)
    mask = Image.open(StringIO(mask_data.content))
    mask = mask.convert(’L’)
    return mask


def download_apps():
    """
    """
    app_ids = [
        "400274934",  # Meon
        "598581396",  # Kingdom Rush Frontiers
        ]

    mask = download_icon_mask()

    [download_app_metadata(app_id, mask) for app_id in app_ids]


if __name__ == ’__main__’:

    download_apps()

Really straightforward, you can download the code here. I find it easy to read (especially since it’s written by me!) understandable, and the code reflects the programmer’s intent. A few notes:

In Objective-C

Let’s see how this script could be written in Objective-C. To this purpose, I’ve used objc-run: objc-run is a shell script which compiles and executes Objective-C source code files on the fly; basically, you’re writing scripts in Objective-C (bonus: it also integrates with CocoaPods).

The source code of the Python script written is Objective-C is now:

/*
 *
 */
void downloadIcon(NSString *iconURLString, NSString *title, NSImage *mask)
{
    NSURL *iconURL = [NSURL URLWithString:iconURLString];
    NSImage *icon = [[NSImage alloc] initWithContentsOfURL:iconURL];
    NSImage *iconMasked = [icon maskUsingMaskImage:mask];

    for(NSNumber *size in @[@1024, @512, @120, @114, @60, @57]){
        NSInteger width = [size integerValue];
        NSImage *iconResized = [iconMasked resizeToWidth:width];

        NSData *data = [iconResized pngData];
        [data writeToFile:[NSString stringWithFormat:@"icon_%@_%ld_%ld.png", title, width, width] atomically:YES];
    }

}

/*
 *
 */
void downloadAppMetadata(NSString *appId, NSImage *mask)
{
    NSLog(@"download_app_json %@\n", appId);

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/us/lookup?id=%@", appId]];
    NSData *resultsData = [NSData dataWithContentsOfURL:url];
    if (!resultsData) {
        NSLog(@"Error downloading %@", url);
        return;
    }

    NSDictionary *results = [NSJSONSerialization JSONObjectWithData:resultsData options:0 error:nil];

    NSDictionary *meta = results[@"results"][0];
    NSString *iconURL = meta[@"artworkUrl512"];
    NSString *title = [meta[@"trackCensoredName"] slugString];

    downloadIcon(iconURL, title, mask);

}


/*
 * Download the mask from Github, this way we don’t
 * have to provide mask.png and the script is self contained.
 */
NSImage* downloadIconMask()
{
    NSURL *maskURL = [NSURL URLWithString:@"https://raw.githubusercontent.com/manbolo/appicon/master/maskInverted.png"];
    NSImage *mask = [[NSImage alloc] initWithContentsOfURL:maskURL];
    return mask;
}


void downloadApps()
{
    NSArray *appIds = @[
                        @"400274934",  // Meon
                        @"598581396",  // Kingdom Rush Frontiers
                        ];

    NSImage *mask = downloadIconMask();

    for(NSString *appId in appIds){
        downloadAppMetadata(appId, mask);
    }
}


int main()
{
    downloadApps();
}

Note: this script can simply be transformed into an executable by commenting the shebang and compiling it with:

clang -g -fmodules -framework Foundation -framework AppKit -o appicon appicon.m

Function by function comparison

Let’s compare the two versions.

The Python script entry point is the function download_apps: given a list of apps ids, it downloads an icon mask and then downloads, masks and resizes each app icons.

The Python source is:

def download_apps():
    """
    """
    app_ids = [
        "400274934",  # Meon
        "598581396",  # Kingdom Rush Frontiers
        ]

    mask = download_icon_mask()

    [download_app_metadata(app_id, mask) for app_id in app_ids]

In Objective-C, this becomes:

void downloadApps()
{
    NSArray *appIds = @[
                    @"400274934",  // Meon
                    @"598581396",  // Kingdom Rush Frontiers
                    ];

    NSImage *mask = downloadIconMask();

    for(NSString *appId in appIds){
        downloadAppMetadata(appId, mask);
    }
}

Appart from the variables’s type in Objective-C, the two codes are very similar, and the Objective-C code remains readable (big thumb up for the Objects literals, Fast enumeration and ARC).

Let’s take a more interesting snippet. In the Python script, download_app_metadata downloads one app’s metadata in JSON, and call a method to compute and save the icons for this app.

In Python:

def download_app_metadata(app_id, mask):
    """
    """
    print("download_app_json {}".format(app_id))

    url = "http://itunes.apple.com/us/lookup?id={}".format(app_id)
    r = requests.get(url)
    if r.status_code != 200:
        print(’Error downloading {} {}’.format(url, r.status_code))
        return

    results = r.json()

    meta = results["results"][0]
    icon_url = meta["artworkUrl512"]
    title = slugify(meta["trackCensoredName"])

    download_icon(icon_url, title, mask)

In Objective-C:

void downloadAppMetadata(NSString *appId, NSImage *mask)
{
    NSLog(@"download_app_json %@\n", appId);

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/us/lookup?id=%@", appId]];
    NSData *resultsData = [NSData dataWithContentsOfURL:url];
    if (!resultsData) {
        NSLog(@"Error downloading %@", url);
        return;
    }

    NSDictionary *results = [NSJSONSerialization JSONObjectWithData:resultsData options:0 error:nil];

    NSDictionary *meta = results[@"results"][0];
    NSString *iconURL = meta[@"artworkUrl512"];
    NSString *title = [meta[@"trackCensoredName"] slugString];

    downloadIcon(iconURL, title, mask);

}

The Objective-C counterpart is still simple and easy to read. I’ve used NSLog to replace printf statement: in my mind, it deals better with Objective-C objects (if you were sneaky, you could argue that the code is readable because it isn’t error proof…).

To get the JSON metadata, I first use +[NSData dataWithContentsOfURL:]. This method has a lot of sister in NSString, NSImage etc… Given an NSURL, there is always a simple way to get an NSData, NSString etc.. from this URL (this method is available since …OS X v10.0 - 2001!)

But, you must be aware that this method is synchronous: it will block the calling thread until the data has been downloaded (or an error occurred). This is perfectly fine in a shell script, but you must always avoid this category of selectors in OSX / iOS apps. By the way, the Python code is also synchronous: r.get() will block until the data has been downloaded.

Finally, to convert the NSData from JSON to a dictionary, I used JSONObjectWithData, introduced in iOS 5 / OSX 10.7. You can say that [NSJSONSerialization JSONObjectWithData:resultsData options:0 error:nil]; is more verbose than r.json() but verbosity is an Objective-C convention, for the better or the worst…

Now, let’s look at the function to download the mask applied on each icon. In Python, I use Requests to download the data, and Pillow to create an Image object with this data.

def download_icon_mask():
    """
    """
    # Download the mask from Github, this way we don’t
    # have to provide mask.png and the script is self contained.
    mask_url = "https://raw.githubusercontent.com/manbolo/appicon/master/mask.png"
    mask_data = requests.get(mask_url)
    mask = Image.open(StringIO(mask_data.content))
    mask = mask.convert(’L’)
    return mask

In Objective-C, I only use Foundation APIs, and once again use a synchronous selector to get an NSImage from an URL:

NSImage* downloadIconMask()
{
    NSURL *maskURL = [NSURL URLWithString:@"https://raw.githubusercontent.com/manbolo/appicon/master/maskInverted.png"];
    NSImage *mask = [[NSImage alloc] initWithContentsOfURL:maskURL];
    return mask;
}

The Objective-C code is still neat and simple. The mask used in the Objective-C is inverted because of the way I will apply it to icons with Quartz. Both masks are black and white, and I was too lazy to make the two scripts work with the same mask.

Finally, let’s compare the masking, resizing and saving functions. The Python code is using a combination of Requests and Pillow:

def download_icon(icon_url, title, mask):
    """
    """
    # Download icon an apply mask.
    icon_data = requests.get(icon_url)
    icon = Image.open(StringIO(icon_data.content))
    icon.putalpha(mask)

    # Compute and save thumbnails.
    for size in [1024, 512, 120, 114, 60, 57]:
        icon_resized = icon.resize((size, size), Image.ANTIALIAS)
        icon_resized.save("icon_{0}_{1}x{1}.png".format(title, size))

In Objective-C:

void downloadIcon(NSString *iconURLString, NSString *title, NSImage *mask)
{
    NSURL *iconURL = [NSURL URLWithString:iconURLString];
    NSImage *icon = [[NSImage alloc] initWithContentsOfURL:iconURL];
    NSImage *iconMasked = [icon maskUsingMaskImage:mask];

    for(NSNumber *size in @[@1024, @512, @120, @114, @60, @57]){
        NSInteger width = [size integerValue];
        NSImage *iconResized = [iconMasked resizeToWidth:width];

        NSData *data = [iconResized pngData];
        [data writeToFile:[NSString stringWithFormat:@"icon_%@_%ld_%ld.png", title, width, width] atomically:YES];
    }
}

Once again, Objects literals simplify the code; it may be only syntactic sugar but I love this addition to the language and hope there will be others soon. The code remains simple and easy to read / write.

In this last function, you may have noticed that -[UIIMage maskUsingMaskImage:] and -[UIImage resizeToWidth:] are not part of the OSX APIs. If you look at the source code of the Objective-C script, you will see that I’ve used small categories on NSImage and NSString. In my mind, this is the equivalent of using a third-party library (Pillow) in the Python code. objc-run is also compatible with CocoaPods, so another possibility could have been to use it.

In Bash

Rely on ImageMagick and jq:

#!/bin/bash
set -eu 

curl -s "https://raw.githubusercontent.com/manbolo/appicon/master/mask.png" >"icon_mask.png"

for app_id in "$@"
do
    metadata=$(curl -s "http://itunes.apple.com/us/lookup?id=$app_id")
    icon_url=$(echo $metadata | jq -r ".results[0].artworkUrl512")
    name=$(echo $metadata | jq -r ".results[0].trackCensoredName")

    icon_base="icon_$name"
    curl -s "$icon_url" >"$icon_base.png"
    convert "$icon_base.png" "icon_mask.png" -compose copy-opacity -composite "$icon_base.png"

    for size in 1024 512 120 114 60 57
    do
    convert "$icon_base.png" -resize "${size}x${size}" "${icon_base}_${size}x${size}.png"
    done
done

rm icon_mask.png

In Objective-Smalltalk

#!/usr/bin/env stsh
#-<void>processIconForApp:appId
framework:AppKit load.
framework:EGOS_Cocoa load.

nonChars := NSCharacterSet letterCharacterSet invertedSet.
str := ’_’.
[ :self  |
   ((self componentsSeparatedByCharactersInSet:nonChars) componentsJoinedByString:str) lowercaseString
] installInClass: NSString  withMethodHeaderString:’slugString’.

mask := http://raw.githubusercontent.com/manbolo/appicon/master/maskInverted.png.
appInfo := ref:http://itunes.apple.com/us/lookup  getWithArgs id: appId

iconURL := var:appInfo/results/0/artworkUrl512.
name := var:appInfo/results/0/trackCensoredName.
icon := context evaluateScriptString: iconURL.

#(1024 512 120 114 60 57 ) do:[ :width  |
  c := MPWCGBitmapContext rgbBitmapContext: width @ width.
  c scale: width / icon pixelsWide.
  c maskedBy:mask draw:[ :aContext | aContext drawImage:icon. ].
  scaled := c image.
  outname := name slugString ,’_’, width stringValue, ’_’, width stringValue , ’_.png’.
  file:{outname} := scaled representationUsingType:4 properties:nil.
].

Recap

On the Python side:

On the Objective-C side:

To my pleasure, the Objective-C doesn’t look too bad, and you can easily get content (text, image, binary) from any URL and work on it in a simple script. But, by limiting your Objective-C script to the OSX world, it really can’t compete with a Python script in my mind. So, I will keep writing my scripts in Python! It has been a fun experiment anyway!

Python source code.

Objective-C source code.

Bash source code.

Objective-Smalltalk source code.

From jc.

How Apple Cheats by Mark Sands

How Apple Cheats by Mark Sands:

Say what?! Did Apple seriously grant access to four of their native apps by hardcoding their bundle identifiers? Yep, they sure did.

In fact, you don’t have to do anything special to verify this. If you change your UIPopoverController Hello World project’s Info.plist bundle identifier to com.apple.iBooks or com.apple.itunesu, then voilà, It works!

Really, it’s in iOS platform interest that Apple own apps and third-party apps play in the same league.

From jc.

iOS 7 Expanded Bluetooth Support

I was aware of some new bluetooth support in iOS 7 but Apple Notification Center Service (ANCS) has completely flown under the radar for me.

The purpose of the Apple Notification Center Service (ANCS) is to give Bluetooth accessories (that connect to iOS devices through a Bluetooth low-energy link) a simple and convenient way to access many kinds of notifications that are generated on iOS devices.

The ANCS is designed around three principles: simplicity, efficiency and scalability. As a result, accessories ranging from simple LEDs to powerful “companion” devices with large displays can find the service useful.

Combined with Application State Preservation and Restoration, developers can create apps that run in background, exchange data with Bluetooth peripherals without the need of user intervention.

I completely miss this!

Really, too smoke for not having a new Apple smart device really soon…

Links

WWDC 2013 - Designing Accessories for iOS and OS X - Session 700

WWDC 2013 - Core Bluetooth - Session 703

Bluetooth SIG press release on Apple iOS and OS X Updates

Apple unlocks full Notification Center access & much more for Bluetooth LE devices in iOS 7

iOS 7 feature focus: Expanded Bluetooth adds support for companion devices, introduces iBeacons

From jc.

iOS 7.1 Gallery

Springboard Springboard1 Springboard2 Fastswitch Fastswitch1 Controlcenter Lock Appstore Appstore1 Appstore2 Appstore3 Appstore4 Compass Compass1 Compass2 Compass3 Calc Calc1 Calendar Calendar1 Calendar2 Calendar3 Mail Mail1 Camera2 Camera1 Camera Clock Clock1 Clock2 Clock3 Contact Gamecenter Gamecenter1 Gamecenter2 Gamecenter3 Imessage Maps Maps1 Maps2 Micro Micro1 Music Music1 Music2 Music3 Music4 Newsstand Notes Notes1 Notifications Notifications_Center Notifications_Center1 Passbook Phone Phone1 Phone2 Reminders Reminders1 Safari Safari1 Safari2 Safari3 Safari4 Safari5 Safari6 Settings Settings1 Settings2 Settings3 Settings4 Stocks Stocks1 Wallpaper Wallpaper1 Wallpaper2 Wallpaper3 Wallpaper4 Wallpaper5 Weather Weather1 Weather2 Itunes Itunes1 Itunes2

iOS 5.0 Gallery

iOS 6.0 Gallery

From jc.

All Posts