|
Daring Fireball's John Gruber recently did another bit on the app store review process. While I usually enjoy his satire (brushed metal anyone?), this one didn't seem quite right. The piece is funny enough, but I hate to think that they are being intentionally cruel or evil. Despite the above quote, I'm not even sure that incompetence is involved at the level of the individual reviewers. I have my own theory on why there are so many rejections and why many highly publicized rejections seem so silly:
By handle, I mean download, install, evaluate, approve/reject and feedback. If this is the case, then the apparent problems result from the fact that rejections can be done quickly (by finding/exaggerating/creating a violation) and that approval takes time (the entire app must be checked against the iPhone SDK Agreement Section 3.3 and its fifteen subsections). In the case of Eucalyptus, The reviewer found it took almost no time at all to reject the app by searching for the Kama Sutra. If the intention was to approve the app, then the reviewer would have had to confirm and checkoff every feature against the long list of guidelines. By quickly rejecting the app, the reviewer can move on to the next item, increasing his number of "handled" apps. Meanwhile, the developer is left feeling bullied and angry. It ultimately ends up a disservice to the millions of App Store users now denied the ability to purchase and benefit from Eucalyptus. This, again, is just my own speculation but it could explain stories like the Tweetie rejection, the NIN rejection, and even the bizarre green icon rejection. It also explains why the feedback emails are often short. There are many examples of mis-incentives across every industry. The New York Times has a great piece on the NBA addressing how focusing on the wrong stats can cost you games. In the early days of phone support, operators were graded on how many customers they handled in an hour. This lead to the operator hanging up in the middle of difficult or long support calls, so they could fish for easier, shorter calls to boost their daily numbers. Customers would become more upset and managers didn't understand why their internal metrics didn't match external surveys of customer satisfaction. You have to incentivize the right metric and apps/hour is not it. The iTunesConnect entity within Apple may or may not believe that the developers it serves are its customers. However, if they don't evolve, refine and improves their service (like Apple evolves, refines and improves its iPods), developers will leave the ecosystem and writers will continue to make fun of them. |
|
An Objective-C class in Cocoa has one hidden object that every knows about. The There is another hidden variable that very few seem to know about:
The most obvious application of
You would typically use it in a method like follows:
This logs a message to the console telling, what method, from what file, invoked with what object. Tremendously useful. Here's a second version that adds thread information:
This method returns an object in a dictionary where the key is the method name,
You could combine this with a property to get easy access inside a dictionary.
If you wanted a read-write property, you could implement it this way:
Now, we have a color property, without ever creating a color instance variable in the class. This has some advantages in that you don't have worry as much about memory management. The object is retained when it's added to SomeDictionary and released when SomeDictionary is released or when the object is replaced. The Objective-C runtime is full of neat little tricks and More advanced techniques can be used to implement some advanced functionality such as higher-order-messaging and even mimic methods as nearly first class objects. Functional programming aficionados can check out http://www.cocoadev.com/index.pl?HigherOrderMessaging for some discussion on this. |
|
The iPhone SDK's UIKit allows extremely versatile touch event handling. With only four methods, Apple has exposed nearly limitless potential for programatic reaction. The problem is that these four methods are essentially exposing the hardware. To do anything interesting or useful, one must wrap meat around these bones. Apple's Event Handling documentation covers several simple cases of touch handling:
Curiously, clear examples for certain basic interactions such as tap-and-hold or pinch-to-zoom are missing. I'd like to rectify that. This recent inclination is compounded by my new-found passion for the au courant open source repository Github. This illicit dyad has produced the creatively named TouchSampleCode. Currently, I've coded examples for the following cases (along with the implicit intention to add more):
The iPhones lack of a keyboard doesn't mean it's not a rich environment for human interaction. The current limitation is not in the hardware, but in the creatively of the developers. Future postings will explore some conjectures on creative uses of the interface. Please consider leaving a tip if you find this useful. These kinds of small tokens are great energizers and tend to encourage more content.
|
|
There are a scattering of iPhone based testing frameworks and utilities: Google's was one of the first. They've apparently built a lot of infrastructure around their solution to fit within existing test systems. With a recent Xcode update, Apple's brought back the original Objective-C test solution. OCUnitIf you're coming from GTM, then the biggest difference is that OCUnit is the integration into Xcode. This means you get IDE errors instead of having to parse the console output (plus!). It also means you have to go to the console to read your log messages, rather than having them display in the built-in console (minus!). This one ships with Apple, but the only clear instructions come from Sente (the original author of OCUnit, back in 1998). Lecture 19 of the Stanford iPhone class had some slides and an example project. Unfortunately, due to the nature of the Stanford website, it's unlikely the slides and sample files will reappear on the website until Lecture 19 is presented for the current semester. Even when the links existed however, the Stanford way didn't give detailed instructions. In the mean time, all I can say is that you trust me when I say that the Stanford way of linking is much easier to do. The Sente method of having the test run every time you build is far superior to the Stanford method (you have to manually change the target and run the tests). If you aren't continually running your tests, they approach a moldy and lifeless state. Here's a set of instructions that take the best of both worlds
Now you have an automated, up to date testing framework in place. Every time you build, you will be immediately notified of any test regressions. The rest is attitude. Xcode will keep the tests running every build, but you have to keep writing tests when appropriate. Sample project available at 6Tringle's github repository. An aesthetic note about header filesTest Case files almost always have an nearly useless header file, so I usually get rid of them, creating single file test cases. The resultant .m looks like this:
|
|
Given that the iTunes App Store population is rising, developers who launched on a prayer aren't always raking in the millions. News posts about 9 year old iPhone developers earning their college tuition overnight seems to have pushed expectations beyond the ceiling of reality. Even the smartest developers are only relying on luck if they don't, gasp, do marketing. Three points from Steve DemeterI had the good fortune to Meetup with Steve Demeter of Demiforce recently. Over the course of about 30 seconds I was able to swindle vital information. It's important for many late-comers to the App Store to remember the early success stories basically don't apply anymore. Apps that were put up early had an extraordinary advantage in terms of visibility. Steve mentioned that new apps need to influence their own visibility and provided a handful of examples how recent apps have. Create Demand Before you releaseSteve talked about the importance of creating demand before release through the use of blogs, YouTube, etc. His example here was Zen Bound. Through the use of YouTube and some good press, the developer had customers "salivating" to buy the app. Get Good Reviews on Day OneIf you app starts off with bad reviews, customers won't wait for your patches and updates to turn it around. You want to start off strong. Good reviews are infectious. If your beta testers love your app, have them positively review it the day it comes out. Resist the urge to cheat. You'll get caught. Use Review sitesUnless your app is terrible, review sites almost always help you. Steve's key insight is to allow review sites early access to the final version of your app before it's available in the store. You want the reviews to be release as near as possible to the review date such that you can move up on the hot lists. Most review sites have a large backlog and thus would need access to the app a couple of weeks ahead of time. Here's a short list. Needless to say, stay away from sites that condone pirated apps, and be wary of those that support jailbreaking. Gruber: "Not all jailbreakers are bootleggers, but all bootleggers are jailbreakers."
It's not a review site, but http://iphone.iusethis.com/ is a nifty site as well. If you testers or customers like your app, kindly suggest they give your app a vote. If you need more helpIn addition to being very tall, Steve's company, Demiforce, is a consulting company specializing in iPhone app and game development as well as promotion and marketing. Steve's a good guy and I'm sure he can help you look good. Disclaimer: 6Tringle is not affiliated with Steve or his company. We have not contracted him to work for us, nor was this post or recommendation solicited by Demiforce or Steve. |
|
Alternative title: You disappear for 2 years and you expect me to take you back? Sorry for not writing sooner, we've been busy. We can explain. Let's just start over, shall we? PhotoClay6Tringle is happy to announce the imminent availability of PhotoClay on the iPhone. It's like turning Photos into Clay, you can push and mold them to your will. We've made it fun and easy to render silly visages of your friends! The cauldron is still bubbling however, and there are a couple of other projects being slow roasted to perfection. We'll let you know more when we can. |
|
Layers of OnionsNSBrowser is an excellent way of interfacing with semi-hierarchically organized data. NSBrowser is part of the NextStep legacy, but achieved real fame through its iPod variant. One reason its effectiveness is that the user can navigate quickly through large sets of data organized by layered attributes. Even more significant, is that the NSBrowser automatically consolidates the user's focus on the current layer. Not only are we navigating large data quickly, but interaction with the current subgroup of data is enhanced by de-emphasizing the remaining data set. This is similar Spotlight's GPU-enhanced screen dimming effect: reduce the user's depth of focus. The well-known Core Data is the best Apple method of handling large sets of data and NSBrowser is the best method of interacting with large sets of data. Surely, there must exist some illicit IB magic bindings or a hidden NSMagicClass capable of combining these parts into a coherent whole. One could easily imagine that an elegant and flexible method to intertwine the powerful data API with the stunningly efficient presentation would be an obvious and welcome chunk of Cocoa. Woefully, the answer is no. NSBrowser's effectiveness is inherently linked to its reliance of hierarchical data. Part of Core Data's strength is that it does not require the model to be hierarchical. In order for Core Data to map to NSBrowser, it is up to the programmer to manually map a model graph to a hierarchal one. In some cases, this is trivial. Certain modal graphs are already hierarchal. Our first example is a simple location database. Countries have States, States have Cities, etc. This is a somewhat trivial example, but further articles will expand on the topic. It's Like Pulling Ducks Out of a HatOn behalf of 6Tringle LLC, I present CoreDataBrowser.dmg! Despite the fact that Steve Jobs would not do this on stage during WWDC, this is a simple exercise. All the work is done in two places: the nib file and CDBrowserDelegate.m. The secret to getting Core Data in an NSBrowser is in the nib file. There are 9 array controllers. 5 of these are auto-generated by Xcode and IB. The remaining 4 are prefixed with "Browsed" and represent the NSArrayControllers used by the NSBrowser to present the slices of data. Looking at the nib file, layer slicing is done via bindings. Inspecting the bindings pane of any of the Browsed array controllers will quickly show that the content set is bound to the parent's current selection. For example, if you inspect the BrowsedStateArrayCon, the content set is bound to the CountryArrayController's selection's states. BrowsedCityArrayCon is bound to BrowsedStates's selections' cities and so on. This is chaining of selections to sets is how we can massage core data into smaller collections of arrays suitable for display in an NSBrowser. Even the most casual observers would notice NSBrowsers similarity to the renowned NSTableView. The programming guide is not exactly a deluge of information, but is more than capable of enlightening those who invest timeffort into it. (Making up words is fun. Squishing two words together? Purecstasy!) Everyday is a Winding CodeThe first thing to notice is that we enumerate our NSBrowser columns in CDBrowserDelegate.h. This is simply good programming practice for static columns. The real work of populating an NSBrowser is done through delegate methods.
We make extensive use of The remaining code is related to updating the browser and keeping it synced with the array controllers. There are two cases to account for:
The first case we use The second case is handled through KVO. We set up the delegate object as observers of the array controllers in the The First Hit is Free...Code mercenaries rejoice, more to follow. |
|
Drawing a line in the groundWhere do you start? When growing a garden, which seed gets planted first? You have the crazy idea for an app that would win accolades, quiet screaming babies and woo the gender of your preference. Now what? Starting an app from nothing can be much more daunting that jumping into a partially or fully finished bowl of code. If you find you self staring at an empty project in Xcode, the ultimate-super-secret is to find an starting point with a low barrier of entry. Do UI love me?When brewing Cocoa, you will always have a GUI. One way to get started is to mock up an app in an image editor or directly in Interface Builder. Since we are at day one, we should create GUIs that get us started, not GUIs where we fuss over pixel widths. If you create a GUI intending to throw it away, you won't fuss over extraneous details. Premature GUI tweaking is a tuber of evil.
It's not pretty, but it will take you about 60 seconds to do in IB. The "browse for file" code will be fast, even if you have never done it before. The key is the big button in the middle. You hook up an IBAction, a few IBOutlets and BOOM. IB will generate the template and your LBoE point is waiting to be filled in like an overdue tax form. Prove it!Another starting point is writing tests. The low barrier here is that writing a test should be easier than writing the code that passes a test. Writing test code may not be interesting, but that's a personal problem. Recent versions of Xcode have a testing framework built in. The whole software testing concept is explored in a diverse medley of websites, books, articles and interpretive song and dance. One way to get get basic functionality started is to write a test. If you know you are going to need some string processing functionality, write a simple test with some example inputs and outputs. I ObjectIf your app is based on Core Data, you can use Xcode's Data Model Design tool to create your model graph.
This is a widget based tool that will get you thinking about your objects by visualizing the relationship between them. As if this LBoE wasn't low enough, you can create a simple GUI by dragging and dropping from Xcode to IB. It's a neat party trick and sure to impress innocent bystanders. Let's just keep things simpleThe lowest of low barrier entry points is a simple list of priorities. This can be done with a text editor or fancy outliner. The outline format maps well; the code will eventually be structured into chunks of functionality, each with sub-functionality. Once your priorities are laid out, draw straws and pretend you are sentencing an item to execution by delete key.
What if we just start over from the middle?It is also important to remember that you don't have to start from scratch. Apple has a trove of example code that can help those new or not so new to Cocoa. The always excellent CocoaDev has an exhaustive list of sample code. If you do find code in the wild, remember to respect the licensees and don't plagiarize. Give credit when it is due. Let's take things a step at a timeIt should be intuitively obvious to even the most casual of readers that the critical action is to just get started. Million dollar ideas are worth approximately $0.02 if they are never acted upon. |
|
Black text on yellow is good for your eyes. Smart people like Micheal Tsai and Wincent Colaiuta even think so. I've been using this set up since the CodeWarrior days (before they went Freescale). Initially, you won't perceive any immediate or significant change. As you get used to the color scheme, in other editors you will notice the absence of kindness to your eyes. We can thank the physiological characteristics of the eye; earth-bound humans are most sensitive to yellowish-green light. The black text on light-yellow allows for high contrast, eye-friendly display. If you Xcode or Textmate, consider giving your eyes a rest. Fully saturated yellow (like a smiley face) is not going to help you at all. By now, you are probably asking yourself, "Self? What kind of yellow do I really want to look at for some ridiculous number of hours a day?" Fortuitously, answers are at hand.
In the Mac OS X color picker, there is a sliders-based option in the toolbar (second from the left on the standard Tiger mini-picker). In the pop-up menu select CMYK Sliders and set everything to 0. Push Yellow up to around 20-25% and you are on your way to being rich and famous. Everything accounted for, color schemes are a very small part of reducing computer related eyestrain. If your eyes are pestering you for some help (itchy, watery, sore, etc.), do some proper research and improve your environment. Happy rods and cones make happy developers. Disclaimer: Results may vary for organisms orbiting red or blue stars. |
|
There are many ways to start an journey. Common aphorisms would misdirect however, as this particular journey began with a thousand thoughts before a single step. A majority of those thoughts were simply forgotten. A lesser but significant number were pondered and discarded. More than a few were loco like a train yard. The tiny remainder form the basis of this site. As long as the resolve holds true and the games stay uninstalled, the blog will be a source of information primarily concerning Cocoa development on the Mac OS X platform. Other topics include web development, infrastructure, and the overall Apple ecosystem. During moments of failed restraint, general nonsense may ensue. Further topics include the acquisition of tokens of commercial value to be used in barter of staples such as food, shelter and iPods. The food will mostly consist of sushi. Our large stable of writers is nonexistent. At present, we have but one stall: Welcome. I hope you come back often. |
about products blog contact misc xml
Copyright 2007-2009 6Tringle Inc