<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Sailing on the Objective-C sea, see?
Written by Cory, from Davander Mobile.@davandermobile on twitter, or email me objectivesea@davander.com

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-6414281-9']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</description><title>Objective Sea</title><generator>Tumblr (3.0; @objectivesea)</generator><link>http://objectivesea.tumblr.com/</link><item><title>wopen 0.2</title><description>&lt;p&gt;I&amp;#8217;ve updated my &lt;a href="http://objectivesea.tumblr.com/post/36331744718/cocoapods-tip-0912-faster-xcworkspace-opening"&gt;wopen&lt;/a&gt; bash function to open the .xcodeproj file if no .xcworkspace is available.&lt;/p&gt;

&lt;p&gt;Copy the alias from here &lt;a href="https://gist.github.com/coryalder/5609996"&gt;https://gist.github.com/coryalder/5609996&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Place in your &lt;code&gt;.bash_profile&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt; file (~/.bash_profile).&lt;/p&gt;

&lt;h2&gt;Example usage:&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;cd projectdirectory
wopen
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;issues &lt;code&gt;open projectdirectory.xcworkspace&lt;/code&gt; if that file exists, or &lt;code&gt;open projectdirectory.xcodeproj&lt;/code&gt; if &lt;em&gt;that&lt;/em&gt; file exists, and errors out nicely if neither do.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/50874228125</link><guid>http://objectivesea.tumblr.com/post/50874228125</guid><pubDate>Sun, 19 May 2013 22:11:02 -0400</pubDate><category>xcode</category><category>cocoapods</category><category>ios</category><category>objective-c</category><category>bash</category><category>shell functions</category><category>programming</category></item><item><title>PhotoDog</title><description>&lt;p&gt;My new app &lt;a href="http://photodog.info"&gt;PhotoDog&lt;/a&gt; was approved late last night! I&amp;#8217;ve spent much of the day sending out press releases, and organizing my social media presence (Instagram and Twitter accounts, mostly). I won&amp;#8217;t write much about that here, as this blog is mostly for technical details, but one thing I&amp;#8217;ve very proud of is that this marks the first production app that uses my &lt;a href="http://github.com/coryalder/DMActivityInstagram"&gt;UIActivity for Instagram&lt;/a&gt;. Presumably someone else has used it, it&amp;#8217;s got a respectable number of stars and forks on GitHub, but this is the first App Store app using it that I know of.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/fefb7b774a8874a7643f5ec1366b2184/tumblr_inline_mik38hICLC1qz4rgp.png" alt="PhotoDog screen shot 1"/&gt;&lt;img src="http://media.tumblr.com/7204ad80d4b8fabcd6ec477366f5b85e/tumblr_inline_mik38n47cM1qz4rgp.png" alt="PhotoDog Screenshot showing DMActivityInstagram"/&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be glad to see it get some battle-testing. :)&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/43629023554</link><guid>http://objectivesea.tumblr.com/post/43629023554</guid><pubDate>Thu, 21 Feb 2013 01:05:00 -0500</pubDate><category>UIActivity</category><category>DMActivityInstagram</category><category>Instagram</category><category>App Launch</category><category>PhotoDog</category></item><item><title>CocoaPods tip #0912: faster .xcworkspace opening</title><description>&lt;h3&gt;UPDATE: 0.2 available here &lt;a href="http://objectivesea.tumblr.com/post/50874228125/wopen-0-2"&gt;http://objectivesea.tumblr.com/post/50874228125/wopen-0-2&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;My typical CocoaPods workflow:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Switch to terminal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt; to your project directory&lt;/li&gt;
&lt;li&gt;Edit Podfile&lt;/li&gt;
&lt;li&gt;type &lt;code&gt;pod update&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Quickly Cmd-tab back to Xcode to close the project before CocoaPods rewrites it&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;open .xcodeworkspace&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Resume working&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The step that trips me up the most of all of these, is ironically step #6. xcw is a hard sequence of letters to type at the best of times.&lt;/p&gt;

&lt;h3&gt;Solution! wopen&lt;/h3&gt;

&lt;p&gt;Put this in your &lt;code&gt;.bash_profile&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function wopen {
    open ${PWD##*/}.xcworkspace
} # open Xcode workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now typing &lt;code&gt;wopen&lt;/code&gt; will open the &lt;code&gt;.xcworkspace&lt;/code&gt; file of the same name as the current directory.&lt;/p&gt;

&lt;p&gt;Typical usage: &lt;code&gt;pod update; wopen&lt;/code&gt;&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/36331744718</link><guid>http://objectivesea.tumblr.com/post/36331744718</guid><pubDate>Thu, 22 Nov 2012 22:48:00 -0500</pubDate><category>cocoapods</category><category>iOS</category><category>Xcode</category><category>Xcodeworkspace</category><category>bash</category></item><item><title>Best Practices: UIButtons and their IBAction/IBOutlets</title><description>&lt;p&gt;Declare the UIButton outlet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Declare the action method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-(IBAction)cancelButtonAction:(id)sender;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when you are writing code you will never confuse the outlet and the action. You will always know what this means:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[self cancelButton];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or even worse:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;self.cancelButton;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s a simple, easy to remember best practice. If you don&amp;#8217;t follow this, or a similar convention (cancelButton/cancelAction) it WILL bite you in the ass one day.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/36265476963</link><guid>http://objectivesea.tumblr.com/post/36265476963</guid><pubDate>Thu, 22 Nov 2012 00:14:16 -0500</pubDate><category>best practices</category><category>cocoa</category><category>IBAction</category><category>IBOutlet</category><category>UIButton</category><category>UIKit</category></item><item><title>AFNetworking - Cancelling operations</title><description>&lt;p&gt;I recently ran into trouble trying to cancel operations in AFNetworking.&lt;/p&gt;

&lt;p&gt;Two issues came up. The first was finding my previous query, to cancel it. The second was receiving some kind of notification that the operation was cancelled. The failure block isn&amp;#8217;t fired when operations are cancelled.&lt;/p&gt;

&lt;p&gt;Since my app uses GET requests, &lt;code&gt;cancelAllHTTPOperationsWithMethod:path:&lt;/code&gt; was failing to find my operation. It was looking for a full path, query string and all. Since the query parameters are off somewhere else in my app, it was much easier to just override this method, and write code to match just the URL, ignoring the query string. Along the way, I improved on this &lt;a href="http://stackoverflow.com/a/13415546/196358"&gt;StackOverflow question&lt;/a&gt; regarding trimming the query string off an NSURL.&lt;/p&gt;

&lt;p&gt;The next bit required digging into the GitHub issues for AFNetworking to resolve. The default behaviour of AFNetworking is to call the failure block if the HTTP request fails, the success block if it succeeds, and do nothing if you cancel it. The logic is that if you are cancelling it, you can probably deal with the cancellation however you want. Details are available in &lt;a href="https://github.com/AFNetworking/AFNetworking/issues/479"&gt;AFNetworking/Issue#479&lt;/a&gt;. The workaround for this is to set the &lt;code&gt;completionBlock&lt;/code&gt; property manually, instead of using &lt;code&gt;setCompletionBlockWithSuccess:failure:&lt;/code&gt;.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/35835948126</link><guid>http://objectivesea.tumblr.com/post/35835948126</guid><pubDate>Fri, 16 Nov 2012 06:39:00 -0500</pubDate><category>AFNetworking</category><category>cancelling</category><category>requests</category><category>HTTP</category><category>iOS</category><category>iPhone</category><category>iPad</category><category>NSURL</category></item><item><title>Get the maximum value in an NSSet using KVC</title><description>&lt;a href="http://funwithobjc.tumblr.com/post/1527111790/defining-custom-key-path-operators"&gt;Get the maximum value in an NSSet using KVC&lt;/a&gt;: &lt;p&gt;You can get the maximum value in an NSSet full of NSNumbers using Key-Value-Coding like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NSSet *set = [NSSet setWithArray:@[ @1,@2,@3,@4,@5 ]];
NSNumber *maxValue = [set valueForKeyPath:@"@max.self"];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Value of &lt;code&gt;maxValue&lt;/code&gt; is now &lt;code&gt;@5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It took me ages to find the correct KVC syntax for this. Source is linked below, and has a bunch of other cool uses of KVC.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://funwithobjc.tumblr.com/post/1527111790/defining-custom-key-path-operators" class="tumblr_blog"&gt;funwithobjc&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(This was prompted by &lt;a href="http://stackoverflow.com/q/4100458/115730"&gt;a recent question&lt;/a&gt; on &lt;a href="http://stackoverflow.com"&gt;StackOverflow&lt;/a&gt;.)&lt;/p&gt; &lt;p&gt;&lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html"&gt;Key-value coding&lt;/a&gt; is one of my more favorite things about Cocoa (up there with &lt;code&gt;NSPredicate&lt;/code&gt;). Basically, it allows you to access properties of objects by name (ie, as a string) rather than invoking a method (er… &lt;em&gt;sending a message&lt;/em&gt;)…&lt;/p&gt;&lt;/blockquote&gt;</description><link>http://objectivesea.tumblr.com/post/34552840247</link><guid>http://objectivesea.tumblr.com/post/34552840247</guid><pubDate>Mon, 29 Oct 2012 03:24:22 -0400</pubDate><category>KVC</category><category>Max</category><category>NSSet</category><category>@max</category><category>NSNumber</category></item><item><title>DMActivityInstagram

A UIActivity class for sharing images to...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_matsegFXW31qgvjk8o1_500.png"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;img src="http://24.media.tumblr.com/tumblr_matsegFXW31qgvjk8o2_400.png"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;h1&gt;&lt;a href="http://github.com/coryalder/DMActivityInstagram"&gt;DMActivityInstagram&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;A UIActivity class for sharing images to Instagram.&lt;/p&gt;

&lt;p&gt;iOS 6 introduced the new UIActivityViewController, which presents sharing options like Facebook and Twitter (as well as printing and copying). I wanted to adapt this for &lt;a href="http://catpaint.info"&gt;CatPaint&lt;/a&gt;, which currently uses &lt;a href="http://github.com/ShareKit/ShareKit"&gt;ShareKit&lt;/a&gt; for sharing. My current Instagram sharer stopped working in iOS 6, and I figured now would be a good time to implement Instagram sharing using this new technique.&lt;/p&gt;

&lt;p&gt;Usage is simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DMActivityInstagram *instagramActivity = [[DMActivityInstagram alloc] init];

NSArray *activityItems = @[self.imageView.image, @"CatPaint #catpaint", [NSURL URLWithString:@"http://catpaint.info"]];

UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:@[instagramActivity]];
[self presentViewController:activityController animated:YES completion:^{}];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hopefully this code will be helpful for other people implementing their own UIActivity sharers, and getting Instagram support in to their apps.&lt;/p&gt;

&lt;p&gt;I would love if someone took an axe to the visual design of the resizer view. It’s not my best work (especially on iPad it looks funny).&lt;/p&gt;

&lt;p&gt;The resizer view is only needed if your app creates non-square images.&lt;/p&gt;

&lt;p&gt;This is not in use in a shipping app yet, but it will be soon.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/32159364967</link><guid>http://objectivesea.tumblr.com/post/32159364967</guid><pubDate>Sun, 23 Sep 2012 19:11:00 -0400</pubDate><category>Instagram</category><category>UIActivity</category><category>iOS 6</category><category>UIActivityViewController</category><category>ShareKit</category><category>cocoa</category><category>objective-c</category></item><item><title>Python syntax checking in BBEdit using Flake8</title><description>&lt;p&gt;I adapted jshell&amp;#8217;s PyFlake gist (&lt;a href="https://gist.github.com/1157742"&gt;https://gist.github.com/1157742&lt;/a&gt;) to work with flake8, and my python setup. Took a bit of tweaking to get the regex right. I&amp;#8217;ve bound it to Cmd-Shift-L, and I&amp;#8217;ve been using it early and often.&lt;/p&gt;

&lt;p&gt;Check it out if you&amp;#8217;re a BBEdit/Python person: &lt;a href="https://gist.github.com/3317713"&gt;https://gist.github.com/3317713&lt;/a&gt;&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/29145399943</link><guid>http://objectivesea.tumblr.com/post/29145399943</guid><pubDate>Fri, 10 Aug 2012 17:00:53 -0400</pubDate><category>python</category><category>bbedit</category><category>flake8</category><category>PEP8</category><category>scripts</category><category>validation</category></item><item><title>Interesting NSURLConnection quirk</title><description>&lt;p&gt;You would expect this code always return a response, sometimes return data, and when there was no data, you could look at the response and the error to determine what happened. Not so! The response object is &lt;code&gt;nil&lt;/code&gt; if it hits a NSURLErrorUserCancelledAuthentication (-1012).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&amp;amp;response error:&amp;amp;error];
if (!data) NSLog(@"Network error: HTTP %i - %@", [response statusCode], error);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Changed to the code below, for now. Not sure how to deal with it long term though, may have to move away from my &lt;code&gt;sendSynchronousRequest&lt;/code&gt; from within an &lt;code&gt;NSBlockOperation&lt;/code&gt; technique of network queuing.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&amp;amp;response error:&amp;amp;error];
if (!data || !response) NSLog(@"Network error: HTTP %i - %@", [response statusCode], error);
&lt;/code&gt;&lt;/pre&gt;</description><link>http://objectivesea.tumblr.com/post/27973986265</link><guid>http://objectivesea.tumblr.com/post/27973986265</guid><pubDate>Wed, 25 Jul 2012 05:47:04 -0400</pubDate><category>NSURLConnection</category><category>NSError</category><category>cocoa</category><category>NSBlockOperation</category><category>networking</category></item><item><title>Addendum (setting up raspberry pi)</title><description>&lt;p&gt;This is pretty cool / useful: &lt;a href="https://github.com/pabloav/raspi-setup/"&gt;https://github.com/pabloav/raspi-setup/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if only for &lt;a href="https://github.com/pabloav/raspi-setup/blob/master/setup.d/05-airplay"&gt;https://github.com/pabloav/raspi-setup/blob/master/setup.d/05-airplay&lt;/a&gt;&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/27657967795</link><guid>http://objectivesea.tumblr.com/post/27657967795</guid><pubDate>Fri, 20 Jul 2012 19:22:00 -0400</pubDate><category>raspberry pi</category><category>airplay</category></item><item><title>Notes from my new Raspberry Pi (arrived yesterday).

Raspbian...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m7hbznseTd1qgvjk8o1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Notes from my new Raspberry Pi (arrived yesterday).&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;p&gt;Raspbian &gt; Arch Linux Arm. Not sure what the deal is with Arch Linux, but it seems to be aimed at the nerdiest of linux nerds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting up Wifi is not easy. My usb wifi dongle was fully supported, but it still took quite a bit to get online. This tutorial was the most helpful &lt;a href="http://wiki.debian.org/WiFi/HowToUse"&gt;http://wiki.debian.org/WiFi/HowToUse&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;a) &lt;code&gt;sudo vi /etc/network/interfaces&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;iface wlan0 inet dhcp
    wpa-ssid your_ssid
    wpa-psk your_password
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;b) &lt;code&gt;sudo ifup wlan0&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;It doesn’t say anywhere that resizing your SD card disk image will take fucking forever. Thought it was crashing because there is no progress indicator. It just takes ~10min (16gb card).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Should have bought a case. It’s not very portable as just a raw circuit board.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now what? Before I got it, I had all these ideas of what I was going to do if mine ever arrived. Now that I have it, I’m a little stumped. Hopefully that will pass. Leaning towards using it to replace my media PC hooked up to the projector, or setting it up for git hosting (with mirroring to dropbox or s3, perhaps?)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;</description><link>http://objectivesea.tumblr.com/post/27653181206</link><guid>http://objectivesea.tumblr.com/post/27653181206</guid><pubDate>Fri, 20 Jul 2012 18:04:00 -0400</pubDate><category>raspberry pi</category><category>technology</category><category>fun</category></item><item><title>Thing #244 I don't like about Xcode:</title><description>&lt;p&gt;Because the structure of your project is abstracted from the on-disc project structure, I always end up with tidy projects and messy project directories.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/21908470762</link><guid>http://objectivesea.tumblr.com/post/21908470762</guid><pubDate>Fri, 27 Apr 2012 08:03:38 -0400</pubDate><category>Xcode</category><category>problems</category><category>apple</category><category>cocoa</category></item><item><title>Respond to a view controller popping off the stack</title><description>&lt;p&gt;I spent quite a bit of time googling this, but couldn&amp;#8217;t find a definitive answer. Basically, how do you detect and respond to being popped off a &lt;code&gt;UINavigationController&lt;/code&gt;&amp;#8217;s stack. &lt;code&gt;viewWillDisappear:&lt;/code&gt; and &lt;code&gt;viewDidDisappear:&lt;/code&gt; both get called when you&amp;#8217;re pushing another view controller on to the stack&amp;#8230; which is not what I want.&lt;/p&gt;

&lt;p&gt;I found lots of misdirection involving &lt;code&gt;UINavigationControllerDelegate&lt;/code&gt;, and &lt;code&gt;UINavigationBarDelegate&lt;/code&gt;, and I almost subclassed &lt;code&gt;UINavigationController&lt;/code&gt;. So far I think this is a better way than any of those. It&amp;#8217;s simple and seems reliable.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-(void)viewWillDisappear:(BOOL)animated {
    NSUInteger ind = [[self.navigationController viewControllers] indexOfObject:self];
    if (ind == NSNotFound) {
        // do something, we're coming off the stack.
    }
}
&lt;/code&gt;&lt;/pre&gt;</description><link>http://objectivesea.tumblr.com/post/21705735018</link><guid>http://objectivesea.tumblr.com/post/21705735018</guid><pubDate>Tue, 24 Apr 2012 03:41:01 -0400</pubDate><category>UINavigationController</category></item><item><title>Tip #293 for writing good Objective-C methods: Fail Early</title><description>&lt;p&gt;Do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- (id)someObject:(DMSomeObject *)caller didSelectView:(DMObjectView *)view {
    if (caller != self.keyObject) return nil;
    ***&amp;lt;LONG METHOD REACTING TO A SELECTED VIEW, RETURNING AN OBJECT***
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don&amp;#8217;t do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- (id)someObject:(DMSomeObject *)caller didSelectView:(DMObjectView *)view {
    if (caller == self.keyObject) {
        ***LONG METHOD REACTING TO A SELECTED VIEW, RETURNING AN OBJECT****
    }
    return nil;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Deeply nested if statements, coupled with blocks based apis or enumeration loops will have you lost in your own code. When possible, fail early for simpler code.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/20399801557</link><guid>http://objectivesea.tumblr.com/post/20399801557</guid><pubDate>Tue, 03 Apr 2012 03:56:43 -0400</pubDate><category>tips</category><category>objective-c</category><category>iphone</category><category>ios</category><category>mac</category><category>code smells</category></item><item><title>Distance function for sqlite3</title><description>&lt;a href="http://www.thismuchiknow.co.uk/?p=71"&gt;Distance function for sqlite3&lt;/a&gt;: &lt;p&gt;This is amazingly useful.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/20398199494</link><guid>http://objectivesea.tumblr.com/post/20398199494</guid><pubDate>Tue, 03 Apr 2012 02:40:01 -0400</pubDate><category>distance function</category><category>sqlite3</category><category>sql</category><category>ios</category></item><item><title>Pictured above, Apple violates all good sense and decency.</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m06krjuwce1qgvjk8o1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Pictured above, Apple violates all good sense and decency.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/18522974445</link><guid>http://objectivesea.tumblr.com/post/18522974445</guid><pubDate>Wed, 29 Feb 2012 19:45:19 -0500</pubDate><category>apple</category><category>ios</category><category>advertising</category><category>iad</category><category>shock</category><category>tim cook</category></item><item><title>Follow up: App Store Spam</title><description>&lt;p&gt;Just a little follow up regarding my post from Dec. 9th regarding the spammy behaviour of one App Store developer &lt;a href="http://objectivesea.tumblr.com/post/13988481450/appstorespam28"&gt;&lt;em&gt;App Store Spam - 28 identical apps&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It looks like he&amp;#8217;s trimmed his armada of white noise apps from ~28 down to 8. I have no idea if this was voluntarily, or if he was forced to remove them by Apple.&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t contacted the developer directly because I&amp;#8217;m not a damn journalist. In this context I&amp;#8217;m just an annoyed App Store user trying to find a good white noise app.&lt;/p&gt;

&lt;p&gt;On that note, I still haven&amp;#8217;t found a good one for iOS. I was contacted by the developer of &lt;a href="http://itunes.apple.com/ca/app/shleepy/id333189314?mt=8"&gt;Shleepy&lt;/a&gt;. He says he made his app free because he wasn&amp;#8217;t making any money off of it anyway.&lt;/p&gt;

&lt;p&gt;Shleepy is great, but it only has customizable white noise. I prefer something with rain / ocean sounds as well. On the mac I&amp;#8217;ve been using &lt;a href="http://itunes.apple.com/ca/app/chill-lite/id434212746?mt=12"&gt;Chill Lite&lt;/a&gt; and it&amp;#8217;s been working wonderfully so far. I expect I&amp;#8217;ll upgrade to the pay version soon.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/16047675717</link><guid>http://objectivesea.tumblr.com/post/16047675717</guid><pubDate>Tue, 17 Jan 2012 23:25:00 -0500</pubDate><category>app store spam</category><category>white noise</category><category>sleep</category><category>follow-up</category></item><item><title>The way iTunes handles podcasts has been dead to me for some...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_lxz7fwNmHZ1qgvjk8o1_500.png"/&gt;&lt;br/&gt; How iTunes presents podcasts&lt;br/&gt;&lt;br/&gt; &lt;img src="http://24.media.tumblr.com/tumblr_lxz7fwNmHZ1qgvjk8o2_500.png"/&gt;&lt;br/&gt; How I want my podcasts presented.&lt;br/&gt;&lt;br/&gt; &lt;p&gt;The way iTunes handles podcasts has been dead to me for some time now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Smart Playlist…&lt;/strong&gt; -&gt; ☒ Match &lt;strong&gt;all&lt;/strong&gt; of the following rules: -&gt; &lt;strong&gt;Media Kind&lt;/strong&gt; is &lt;strong&gt;Podcast&lt;/strong&gt; -&gt; &lt;strong&gt;Plays&lt;/strong&gt; is &lt;strong&gt;0&lt;/strong&gt; -&gt; ☒ &lt;strong&gt;Live Updating&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Problem &lt;em&gt;approximately&lt;/em&gt; solved.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/16046722049</link><guid>http://objectivesea.tumblr.com/post/16046722049</guid><pubDate>Tue, 17 Jan 2012 23:07:00 -0500</pubDate></item><item><title>"Hi, I have an app that I feel is pretty good, but has a shit name (Saline). I’ve been thinking about..."</title><description>“Hi, I have an app that I feel is pretty good, but has a shit name (&lt;a href="http://itunes.apple.com/ca/app/saline/id416028858?mt=8"&gt;Saline&lt;/a&gt;). I’ve been thinking about re-releasing under a new, more search friendly name. Would you consider that spam too? I agree this George dude is over the line though.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.unled.net"&gt;unled&lt;/a&gt; in response to my &lt;a href="http://objectivesea.tumblr.com/post/13988481450/appstorespam28"&gt;previous post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I absolutely don’t think that would be spamming the App Store. Even if you keep the old one in for a bit to do a little A/B testing. As long as you drop one after a bit, or differentiate the two apps in some meaningful way (i.e. functionality).&lt;/p&gt;

&lt;p&gt;Personally I would just submit an update that re-brands my app, rather than put a new app in the store.&lt;/p&gt;

&lt;p&gt;I don’t hate marketing, I just know that marketing means you walk a fine line between promoting a product and gumming the world up with spam.&lt;/p&gt;&lt;/em&gt;</description><link>http://objectivesea.tumblr.com/post/13999575519</link><guid>http://objectivesea.tumblr.com/post/13999575519</guid><pubDate>Fri, 09 Dec 2011 23:04:22 -0500</pubDate><category>marketing</category><category>ios</category><category>app store spam</category><category>feedback</category></item><item><title>App Store Spam - 28 identical apps</title><description>&lt;p&gt;In August, iOS developer George Talusan put 22 identical copies of the same app in the App Store. That&amp;#8217;s &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewArtistSeeAll?dkId=11&amp;amp;ids=289224719&amp;amp;softwareType=iPhone"&gt;22 times, under 22&lt;/a&gt; different names.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://i.imgur.com/oNAMa.jpg" width="500"/&gt;&lt;/p&gt;

&lt;p&gt;When I discovered this, a few months ago, I reported it to Apple immediately. Since then, he has put the same app in another 6 times, with a &lt;em&gt;slightly&lt;/em&gt; modified UI. Apple does not seem to have responded.&lt;/p&gt;

&lt;p&gt;I stumbled on this honeypot of apps while looking for a white noise generator during a bout of insomnia. The screenshot looked attractive and it was free, so I downloaded it. I&amp;#8217;ve tried a few other noise generator apps, and this one was definitely not a good one. The sounds were alright, but it stopped playing sound the moment my phone went to sleep. Most other noise generators will continue playing. That said, even if this app was god&amp;#8217;s gift to iPhones, it wouldn&amp;#8217;t excuse the 28 copies spamming the App store and Clogging up your search results.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://i.imgur.com/0JSiJ.jpg" width="500"/&gt;&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;small&gt;(Three variations on the one UI, depending on when this duplicate was last updated)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Some of the copies of the app are free, and some of them are $0.99 or $1.99. They all seem to have an in-app purchase to unlock the full feature set.&lt;/p&gt;

&lt;p&gt;He&amp;#8217;s since fixed the issue of background audio in some, but not all, of the duplicates. I&amp;#8217;m sure it&amp;#8217;s hard work keeping 28 apps up to date.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s in the store under the names Virtual Earplugs, Ambient Soundscapes, Power Nap - Soundscapes, iEarplugs, Noise Block, Brain Tuner - Focus, Nap+, iRelax - Soundscapes, Napbot, Meditator, Mood Tweak, Toga Sound, Dreambot, Babywaves, Hushbaby, iDream -Sleep Maker, iPacifier, SleepAid - Soundscapes, Mood Mod, Tuneout - Sound Blocker, Soundwaves, and Focus+. In December he added Soundscaper, Soundscaper Pro, Sound Oasis, Sound Oasis Pro, Sleep Maker and Sleep Maker Pro.&lt;/p&gt;

&lt;p&gt;These apps are listed in the categories: Utilities, Productivity, Travel, Business, Medical, Lifestyle, Heathcare &amp;amp; Fitness, and Education.&lt;/p&gt;

&lt;p&gt;This is a pretty big failure in the app approval process, and I&amp;#8217;d be willing to bet it&amp;#8217;s not an isolated incident. Each of these has been looked at by a real human being, who no doubt had access to their account history. It doesn&amp;#8217;t take a genius to spot that these apps are all IDENTICAL. From what I can see without buying them all the only thing that varies between them is the icon, the name, and the app description. Either they have no directive to stop stuff like this from happening, or they have no system in place to catch it.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d love to hear about other examples of this kind of App Store SEO/spam.&lt;/p&gt;</description><link>http://objectivesea.tumblr.com/post/13988481450</link><guid>http://objectivesea.tumblr.com/post/13988481450</guid><pubDate>Fri, 09 Dec 2011 18:57:00 -0500</pubDate><category>apple</category><category>app store</category><category>app store spam</category><category>white noise generators</category><category>sleep</category><category>iphone</category><category>ios</category></item></channel></rss>
