Sunday, November 10, 2013

Dropbox Core API with blocks

I've been adding support for Dropbox to FTP On The Go!  Because it needs full access so you can upload any file from your Dropbox, or download a file to any folder, it has to use the low level "Core"API.

The code from Dropbox is good, but uses delegates for everything.  I didn't want to have lots of checks for "file download complete" to see what to do with it next--edit/view, email it, upload it to an FTP server, or any of the other things.  With several operations potentially happening at the same time, that could get confusing :)

So I made a little wrapper for the DBRestClient to do Blocks.  The code for getting the metadata, like a folder's contents or details about a file, is below.  There are similar functions for all the other things, uploading or downloading files, etc.  I'll post all that once the new version of FTP is out.  (But as you can see it's a dozen or so lines of code for each one you'd want to do so pretty easy to add yourself.)


The .h
@interface DBRestClientBlock : DBRestClient 

@property (nonatomic, copy)  void (^loadedMetadata)(DBMetadata *metadata, NSError *error);

+ (DBRestClientBlock*)dbClient;

@end


The .m
@implementation DBRestClientBlock //DBRestClientDelegate

+ (DBRestClientBlock*)dbClient {
    DBRestClientBlock    *dbBlock = [[[DBRestClientBlock alloc] initWithSession:[DBSession sharedSession]] autorelease];
    dbBlock.delegate = dbBlock;
    return dbBlock;
}

//Metadata Downloading...
- (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata {
    NSLog(@"loadedMetadata");
    if (self.loadedMetadata) {
        self.loadedMetadata(metadata, nil);
    }
}
- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error {
    NSLog(@"loadMetadataFailedWithError");
    if (self.loadedMetadata) {
        self.loadedMetadata(nil, error);
    }
}
@end


Then you get to do nice bits like:

DBRestClientBlock   *dbClient = [[DBRestClientBlock dbClient] retain];
dbClient.loadedMetadata = ^(DBMetadata *metadata, NSError *error) {
        if (metadata) {   
     //Do something with the results
        }
        if (error) {
            NSLog(@"loadedMetadataError: %@", error);
        }
        [dbClient release];
};
 
[dbClient loadMetadata:pathToLoad];


(I've also got a manager class, that caches these DBRestClientBlock objects too.)

Wednesday, November 6, 2013

iPad Pro...

If you make an iPad Pro, with a bigger screen, what does that really mean to the pixels?

You can either keep the same 2048x1536 size of the current iPads and make bigger pixels or do a new screen resolution.

Keeping the same 2048x1536 pixels lets you make anything you'd want and every app works as-is. Just like the non-transition from iPad to iPad mini where everything just worked, the pixels would simply be bigger rather than smaller.  But bigger pixels will start to get below Apple's magic Retina numbers.


Instead you could also increase the resolution. The next nice "computer" numbers up that keep the same aspect ratio would be 2560x1920.

You could again make those pixels any size you want.  If you use exactly the same size pixels as the iPad Air, you go from a screen rectangle of 7.76" high by 5.82"wide up to about 9.7" by 7.28" which gets you a diagonal of around 12.13".  That seems a little big, but again you could make new LCD panels whatever size you want.  But it's in the ballpark for the screen size from various rumor websites.

Existing apps would run as-is, with a black border, much like iPhone-only apps on an iPad, or "short" apps on an iPhone 5 with the taller screen.  Apps that were boxed in wouldn't look as good, but they would work fine.  The pixels (so buttons and such) are the about/exactly same size as the iPad Air, so it would all be usable as apps get updated.


Where it gets even more interesting is if you make an iPad with the pixel size of the iPad mini, but make it that new 2560x1920 pixel count. By my math, you'd end up with a screen that is 7.85" x 5.89" which is within fractions of an inch of the size of the current iPad Air screen (7.76" x 5.82"). That seems like the iPad Air 2 next year.


So if you do an iPad Pro spring 2014, with a bigger screen and higher pixel count, apps will get updated. With the bigger device, apps would be usable at the old size as they're getting updated.  Then you can roll that new pixel count back into the iPad Air2 in fall 2014.  iPad Air2 gets an even sharper screen, and a nice new differentiator from the iPad mini if it stayed 2048x1536 (which I think it would).

Developers will jump on the Pro so all apps that matter would have been updated by the fall 2014 time.  (Many would even get updated in the week or two between the announcement and its release.)

This also gives more choices for updating the models later.  Air and Mini updated in the fall in time for the holidays, Pro which would be more a business iPad and gets updated in the spring.  Pro could even get a few goodies from current and future iPhones that the fall iPad Air/Mini didn't get...like I'd be very surprised if it didn't have TouchID.


*Assuming I've not screwed up the math too much.

Monday, November 4, 2013

Hackathon

I went to my first Hackathon this weekend.  A bunch of people, in teams of up to 5, trying to build something cool that could be the foundation for a company in just 24 hours (or just trying to build something cool or fun in the 24 hour time too.)

I'd brought an idea, for an NSA-proof messaging app.  We now know that between spying, hacking, and court orders, just about any connection over the Internet is susceptible to "man in the middle" attacks or all sorts of other monitoring techniques.

My idea, Funsa (or F.U.NSA) was that if you treat the whole Internet as compromised, then the way to communicate securely is to exchange the keys for your messages off the Internet.

I sat down at a table, and happened to get the right people there.  An Android developer and web services guy both from Amazon.  A woman joined us later who did IT security and was a great researcher and presenter for the team.

(Team website here)


We got a working demo for iOS to show.   Each device would make a new 2048 bit RSA public/private key pair for a new connection.  Then they would exchange the public keys between the two iPhones over Bluetooth.  From then on, they could use those keys to send secure messages using a server over the Internet, using the keys they'd exchanged offline.

A real app might use 4096 bit keys (but that could take several minutes to generate on an older iPhone--so we did 2048 for the demo since it "only" takes a few seconds on the new iPhone 5S.)

We talked about all sorts of next steps and other ideas.  
  • Sending the keys using QR codes on the phone screens and front cameras, even sound and squawking like a modem from the 90s.
  • Lots of features for enterprise like having full source code so they could audit and setup their own controlled messaging servers.
We got to the finals (top 6 out of about 30), but didn't get in the top 3.  But many people said that if it was on the name alone, we'd win :)

Pete, Shawn and I talked about finishing it up as a Headlight app.  Pete had some great ideas; since he's in London, the bluetooth way of exchanging keys wouldn't work :)  The craziest would be to each print out QR codes for the public keys and send them by regular snail-mail to scan on each of our devices across the world!


Offline key exchange wouldn't be new--that's one of the reasons why they invented handcuff briefcases you see in movies :)  We didn't find any apps or message systems that used it as the security method for mobile devices.

Sunday, October 27, 2013

iPad TouchID

I'm sure one of the reasons the new iPads this year didn't get the fingerprint TouchID is simply it would be hard to make enough for all the iPhones and iPads they're going to sell.  (And I've not looked into how thick the part is compared to the thickness of the devices, that could be an issue too.)

But another reason...

iPhones are very personal, you might let your kids borrow it, but they aren't really shared within a family, much less to a guest.

But iPads are much more often shared.  One of the things that iOS has lacked, and hopefully will come in 8, is some sort of user accounts.  So when the parents use it, they get Safari with their own bookmarks; their own email, Facebook, and other accounts; their own apps.  When a kid uses it their apps are restricted to PG ones, Safari or email might not be there at all, and they can't install new apps or other restrictions. All settings the iPad can do, but right now it's globally, not per user.

Without something like that, TouchID that only unlocks the device is nice but a missed opportunity for instant and easy personalization.  Kid's fingerprint--gets kids account.  Mom or Dad--they get their own accounts.

All that together seems a worthy upgrade for iOS 8 and the 2014 iPads.

Even do a nice setup when making an account.  A few choices that set the basics for what is restricted that you could customize.  "Adult"=All  "Teen"=R  "Pre-Teen"=PG  "Toddler"=G

Wednesday, October 23, 2013

iPad 2

I thought it was odd that the iPad 2 was kept around for sale.  Why not do the iPad 4 as the older model?  The new Air is a big enough step forward, especially over that even thicker and heavier model.

Then I thought of a reason:  Lightning.  The iPad 2 is the model that still had the old style 30 pin connector, which is used for a variety of devices like Point of Sale terminals.  And who knows what industrial uses it might have.

Rather than bring back the iPad 3 with the old connector (which would be weird since it's been off the market for a year) keeping the iPad 2 makes a little more sense.  And give its older technology, the profit margins on that one must be huge.

Wednesday, October 16, 2013

Older Models

Historically, when Apple released a new iPad, iPhone, or iPod touch, it has very often kept around last years model at a reduced price.

And most of the time it's one model, with the same or less storage compared to the low end of the "new" model, and $100 cheaper.

Does that mean next week we'll see a 16GB model of the current iPad mini stay on sale...for $229?  Interesting if they do, that's the same price as the low end 16GB iPod touch.  I'd guess they'd either drop the iPod touch price a little to $199, or make that model iPad mini be $249.

They've never increased the price of iPads, but this might be the time to do the Retina mini at $349 and the current non-retina at $249.  Keeps that $100 price separation.

Thursday, October 10, 2013

iOS7 parallax shadows

It looks cool enough, we're doing it anyway, even though "floating above" is more normal in iOS7 than "shadowed behind".

To my eyes it is a more subtle and less jumpy depth effect.  The content you're looking at isn't moving, but the shadows it casts are.


@implementation UIView (Giffish)

- (void)addShadowing {
    [self.layer setShadowColor:[UIColor blackColor].CGColor];
    [self.layer setShadowOpacity:0.4];
    [self.layer setShadowRadius:3.0];
    [self.layer setShadowOffset:CGSizeMake(0, 2)];
}

- (void)addShadowParallaxMotionEffect:(float)amountAndDirection {
    float       amount = 10.0*amountAndDirection;
    UIInterpolatingMotionEffect *motionX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.shadowOffset.width" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
    [motionX setMaximumRelativeValue:@(amount)];
    [motionX setMinimumRelativeValue:@(-amount)];
    UIInterpolatingMotionEffect *motionY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.shadowOffset.height" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
    [motionY setMaximumRelativeValue:@(amount)];
    [motionY setMinimumRelativeValue:@(-amount)];
    UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];
    group.motionEffects = @[motionX, motionY];
    [self addMotionEffect:group];
}

@end


//You'd want -1.0 to start.  See how that looks and adjust.  
[button addShadowing];
[button addShadowParallaxMotionEffect:-1.0];  

//This type of thing works too.
[button.titleLabel addShadowing];
[button.titleLabel addShadowParallaxMotionEffect:-1.0];