显示标签为“App”的博文。显示所有博文
显示标签为“App”的博文。显示所有博文

2011年12月20日星期二

Using Storyboards To Make Navigation Based iPhone Apps

Using Storyboards To Make Navigation Based iPhone Apps:


Over the past few weeks I’ve been doing a series on using the new storyboard feature in XCode for iOS apps. The short story here is that we can now compose our iOS apps in a completely new way when we are coding apps in iOS 5. Storyboards are not backward compatible.

Today, I’m going to show you how to using storyboards to create a navigation based app, with and without a table view. If you haven’t already done so, be sure to read my previous two posts on storyboards in iOS:


Step One: Create a New Storyboard Based iOS Application


Make sure to have a storyboard app started out (covered in the last post on storyboards). Your app will look something like this:


Step Two: Delete Default Scene


We need the navigation controller to be the first scene in our storyboard, so we’ll need to remove the scene that XCode place here for us. Select the scene right in Interface Builder and hit the delete button. You will be left with an empty storyboard.

Step Three: Add A Navigation Controller


Use the object library to drag a navigation controller unto the storyboard. XCode will insert the navigation controller and make it the first scene on the storyboard for you automatically. You will also get the root view controller automatically setup and connected with a seque already connected.

Step Four: Add A Button To The First Scene


Select the scene with the title Root View Controller. Use the object library to drag a button onto the root view controller. Set the button title to Red. It should look something like this:

Step Five: Connect A New Scene To The Button


Now we want to move to a new scene when users touch the Red button. Drag a new view controller from the object library into the storyboard and change the view controller’s background color to red.

Then control-click the button and drag the blue line to the view controller. Choose Push for the seque type. Your storyboard will look something like this:



That’s all there is to it when setting up navigation. Now, I’m going to be clever and add more than one scene to my navigation project. Here is what my storyboard looks like:



This app will push new color scenes to the navigation controller based on what button the user presses. All with no coding at all yet.

Step Six: Pushing Model Content Across Scenes


Usually, when you are working with apps that support navigation you are following the Model-View-Controller (MVC) design pattern. This means that one view controller will need to pass a reference to the part of the model that will be presented in the next view controller. So, here our root view controller might need to pass something to the detail view controllers that we have set up here.

Before, this was done as part of the IBAction associated with a user control or in the table view delegate method didSelectRow:atIndexPath: . But, now we don’t have any code associated with these transitions. Luckily, we can get references to the storyboard components from within our view controllers.

So, all we need to do to pass on model references during these storyboard transitions is to override one of these two key UIViewController methods:

- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;

To use these method you must make sure that your view controller has a custom code class associated with it. For our example, to set the custom class for our root view controller we can simply use the ViewController that was originally created for us by XCode.

But, we’ll have to set the custom class identity of the view controller on the storyboard to ViewController using Interface Builder.

So, click on the root view controller on the storyboard to select it and then use the Identity Inspector to set the view controller’s custom class to ViewController .



Great, now you can put code into ViewController and it will execute during key events like seque transitions.

In my contrived example, I am going to simply change the view controller’s title property to the text title on the button that the user pressed just to show you how its done:

#import "ViewController.h"

@implementation ViewController

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ UIButton *button = (UIButton *)sender; UIViewController *vc = [segue destinationViewController]; vc.title = button.titleLabel.text; }

@end

Now, when you go from the root view controller to a detail view the title property (in the navigation bar) will change as well. Again, this where you would do something meaningful with your model content.

That’s it for now – keep your eye out for some more storyboard related posts coming out in the near future. Let me know what you think about storyboards in the comments below!

2011年11月10日星期四

Beta Testing iOS Apps Made Easy [Boon Chew]

Beta Testing iOS Apps Made Easy [Boon Chew]:
The success of iOS platform has spurred the creations of third party solutions that make make aspect of iOS development less painful such as in-app purchase, push notifications and backend integration provided by companies like Urban Airship and Parse. TestFlight is one such service. It was created to help facilitate your beta testing and lets you distribute your beta build over the air – made possible by the wireless app distribution model added in iOS4.

Let’s take a quick look at what TestFlight is all about and what they offer. For a complete overview of the latest and greatest of the service, you should of course sign up and visit the site directly. If you are already using TestFlight for your beta testing, you can also skip this and go straight to the next section.

1) Sign in after registration



2) Check the email on any of your test devices and login:



3) Tap Register Device to send your UDID over to TestFlight.



4) TestFlight sends back the provisioning profile over the air. What are you waiting for, tap Install!



5) Your device is now registered with your TestFlight’s database.



6) Now that you have registered some devices for testing, let’s submit a build to TestFlight.



7) We created the adhoc build in Xcode, saved the ipa file in Organizer, went to the folder where the ipa file is stored and dropped it here. Notice that it’s quite a bit of work — we will discuss how to automate this step without relying on Xcode later in this article, giving you a more pleasant test flight. :)



8) When your ipa file is done uploading, this is what you will see, and it’s where most of the power of TestFlight lies. Particularly, pay attention to the left pane: History shows you the upload history of each build of the app, along with feedback sent by testers (from within the app), crash reports, test session info (such as what your testers have tested and how long), etc.

(Names and photos have been blurred to protect the innocence)



9) Crashes has got to be the #1 concern when it comees to testing. Be sure to upload your dSYM file so TestFlight can make sense of the crash reports coming from your build.



10) This is an example crash report received from a test run of an app we worked on. Sexy, no?



At this point, assuming we have convinced you enough to start trying out TestFlight, here comes one last goodies. (Names and photos have been blurred to protect the innocence)

Step (7) and (9) requires that you mess around with doing the build and uploading your ipa file and dSYM file to TestFlight. Wouldn’t it be nice if this can somehow be taken care of as well? Well, you have chosen the right profession. All you need is create a shell script to automate this task and to save you time, we have created a script to do precisely that. If you are a gluten for punishment, you can skip the following and continue to use the good old Xcode way.

Quick HOWTO:

1) Save the script above to build.sh

2) chmod +x build-ipa.sh

3) ./build-ipa.sh

Let’s take a look at the script to automate the building and submission of our app to TestFlight:

#!/bin/sh
ProjectPath="~/Projects/Test/"
Target="TestApp"
AdHocPath="build/AdHoc-iphoneos/"
AdHocConfigurationName="AdHoc"
DeveloperName="zitao xiong"
ProvisionFile="8490865F-4F60-41BA-98EA-EA2E7B470CF2.mobileprovision"
ipaName="testflightapp"
api_token="your test flight api key"
team_token="your test flight team token"
notes="Beta build #1"

// Step (1)
xcodebuild -target "$Target" -configuration ${AdHocConfigurationName}

// Step (2)
xcrun -sdk iphoneos PackageApplication -v "${AdHocPath}${Target}.app" -o ${ProjectPath}${ipaName}.ipa --sign "${DeveloperName}" --embed ${ProvisionFile}

// Step (3)
pushd .
cd ${AdHocPath}
zip -r ${ipaName}.app.dSYM.zip ${Target}.app.dSYM/

// Step (4)
popd
curl -v http://testflightapp.com/api/builds.json \
-F file=@${ipaName}.ipa \
-F api_token="${api_token}" \
-F team_token="${team_token}" \
-F notes="${notes}"\
-F notify=True \
-F replace=False \
-F dsym=@${AdHocPath}${ipaName}.app.dSYM.zip

// Step (5)
rm ${AdHocPath}${ipaName}.app.dSYM.zip

Explanations:

Step (1) Here we use the xcodebuild command to build the project of our choice. Configure the target name and the configuration profile in the shell variables above it. In our case we are doing an adhoc build for our TestApp.

Step (2) We then use xcrun to create the ipa file. The command also takes care of embedding the provisioning profile into the ipa.

PackageApplication is a perl file locate at /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication

The rest should be self-explanatory.

NOTE: In case you are curious, ipa stands for iPhone Application. It’s technically a folder, though a folder is considered as a file in Unix.

Step (3) After the ipa file is generated, the script proceeds to zip up the dSYM folder. This way when TestFlight receives a crash report from your beta builds, it will be able to make sense of things in the event that you have configured the build setting for the build process to strip the debug symbols out of the build (e.g. to reduce file size).

NOTE: We use the Unix command “pushd .” to save where we are at before traversing into the build folder so we can return later with “popd”.

Step (4) We are now at ready to send the build off to TestFlight. Retract back to the project folder and use curl command to do the delivery. The parameters should be self explanatory so we won’t get into them.

Step (5) Finally we remove the dSYM zip file to keep things clean. You may choose to skip this step if you wish to keep it around for later use.

With the build uploaded to TestFlight, you can now notify your beta users to start testing it away! Thanks for flying with TestFlight and we hope you will fly with us again.

Disclaimer: This article is the result of our subject evaluation with TestFlight. We are in no way affiliated with TestFlight and have received no bonus miles in promoting their service.

2011年11月3日星期四

Submitting Your First Mac App Store App

Submitting Your First Mac App Store App:
I would say I have the process of submitting iOS apps down, I could probably do it blindfolded. Actually I HAVE done it blindfolded on several occasions guiding people over the phone on their very first submission.

But today I am doing it for the first time on an app for the Mac App Store (aka MAS). Let’s see if I can see this through to a successful conclusion, or at least until the ball is out of my court and with the app review team.
A couple of months ago we made a deal with BytePoets, a small software company based in Graz, Austria. At that time I had an idea for a Mac tool that would greatly simplify how you localize apps. But at the same time I was afraid of starting to code on OSX. I did not have the time to devote to this project to get up to speed myself, so I let them do the development. Publication and marketing of the app now falls to me.

Certificates and Profiles


So as the first step – I figured – I probably need a distribution certificate for the app. So I logged into the Mac Developer Center and went looking for the Mac equivalent of the provisioning portal. I found the “Developer Certificate Utility”, which sounded like what I needed.



First thing to do there was to register an app ID. You choose an app bundle identifier similar as you would do on iOS, in reverse domain notation with the final part being the name of your app. Also you give the identifier a name or description so that you find it later.




The second step is to confirm your input as you can only delete such identifiers from your account, but you will never be able to edit them.

On the screen that follows you can configure iCloud and Apple Push Notification support for the app, but we didn’t need those at this time.

On the Certificates tab I was confused to see a Mac App and a Mac Installer certificate already there. I didn’t recall creating these. So I ignored them for the time being and clicked the big blue button to request a new certificate.

Then I felt at home again, you get a choice to create a developer or a distribution authority and just like on iOS you have to use the certificate assistant in your Keychain Access to get these. The assistant creates the private key in your keychain and you save the public key to a file. This you upload to Apple and they sign it. Then at the end of the process you download their result and it joins the private key in your keychain when you open it from your downloads folder. You have to create two distinct signing requests for a development and a distribution identity.

The product of this is that you end up with 5 certificates on your keychain, the “iPhone Developer/Distribution” you have seen before, as well as two new ones titled “3rd Party Mac Application” and “Mac Developer”. Looks ok, if all 5 certificates have the private key dangling under it.

On my first run through here I forgot about the second distribution profile for the MAS, you need to have both a Installer and Application certificate for that, where with iOS this is only one certificate. If you don’t get the Installer certificate then you will find that you cannot validate or submit apps, instead you get stuck with “Don’t sign package (No valid signing identities found)”.



The third tap is titled Systems and looks to be the same as where you enter your iOS device IDs. For practice I went ahead and registered my MacBook Air. I didn’t know that even Macs had hardware device identifiers! You can find the one for your machine on the “About this Mac” and then look for “Hardware UUID”.

Just like with iOS you are apparently limited to registering 100 such systems per year. Obviously this has to be only for testing purposes, like iCloud and Push Notifications, right?

The fourth and last step is to titled Provisioning Profiles, again a concept we met in the iOS world. Again a big blue button leads to a selection between either Development or Production, where I believe the latter to mean the same as Distribution.

For a Development profile you specify a name or description, choose the previously generated bundle identifier, select the systems that are allowed to run this and the developer certificate. For the Production profile I was presented with two Mac Application Distribution Signing Certificates, so I chose the one with a later expiration date. That must have been one of the two that I saw earlier, but couldn’t remember creating. Naturally production apps don’t have any restriction regarding systems, so this is grayed out.

Once the button on the following page turns from Processing to Download you get to see a new pref pane that you never noticed before. Just like on iOS there is also a profiles section in your system settings.



One thing that stumped me at first was that I got an error message when I tried the same exercise with the production provisioning profile which happens automatically after download. I suppose that you cannot install a production provisioning profile in your profiles pref pane because it does not have your device identifier. Also on iOS you wouldn’t ever install the app store distribution profile on a device.

Adding these new provisioning profiles to the Xcode organizer, under devices, worked fine. You can see my automatically managed team provisioning profile for iOS and the two new Mac provisioning profiles. And actually this confirms what I suspected for the production profile: “This profile cannot be installed on devices”. Aha. Thanks Apple for letting me think for a few minutes that I did something wrong …



That seems to be all in terms of general setup, next I did a fresh checkout of the app’s trunk from my Subversion repository … and made a fresh cup of tea to calm my nerves, I’ve started getting sweaty palms from all the excitement.

Creating a New App on iTunes Connect


Before getting into the intricacies of building the app I had to do the work required for apps on iTunes Connect to get a new app id number which is needed for the “Rate this app” button. This number is assigned by Apple when you create the app on the iTunes Connect portal.

So I logged into the well known http://itunesconnect.apple.com, clicked the “Add new app” and chose Mac OS X App.

You choose a name for the app, an SKU code (I usually take the app name in upper case characters) and choose the correct bundle identifier which we created earlier. You are again reminded that “the Bundle ID cannot be changed if the first version of your app has been approved or if you have enabled Game Center or the iAd Network.”



Next you select the availability date and a pricing tier as you are used to.

On the third screen you have the usual elements to fill out, a description, rating, URLs. Been there, done that.

The first problem I ran into was to provide an acceptable screen shot. Earlier I had simply opened the app and made a screen shot of the app window. Turns out it must be a JPEG, TIF or PNG file that is 1280×800 or 1440×900 pixels, at least 72 DPI and in the RGB color space. A bit of a problem for me on a MacBook Air, since the maximum resolution there is 1366×768.

The trick I used was to switch the display to 1152×720 (stretched), put the app in full screen mode and make a screenshot with Shift+Cmd+3 to not get a shadow. This was easily upscaled to 1280×800 by means of the Preview app. This PNG was accepted without problems.

After a nerve-wrecking long wait on hitting the Submit button, the creation of the app worked and I got my app identifier. I found it odd that there was no means to upload an app icon, but I figure that the icon contained in the app bundle is probably of sufficient resolution for Apple to take it from there.

Building the Code


So back to Xcode where I had the app already running in debug so that I could make the screenshot. So first check was for which mode the Archive scheme was set: release. Next I went into the target settings and adjusted code signing to match my production provisioning profile, the “3rd Party Mac Developer Application” option.



Building the code for the first time like this triggered lots of warnings that seem to come from using attributes in xib files that are not supported prior to 10.7. I also found a warning about receipt validation (by Nick Paulsen) not being enabled, I had heard about this mechanism that allows Mac apps to validate their honest origin as the MAS.

So I enabled the define after adjusting the bundle identifier (com.drobnik.Linguan) and bundle version (1.0), to see several linker errors. I had to add the IOKit, Security and libcrypto dynamic libraries to fix these.

After that the Archive build went right through and appeared in the Xcode organizer. I tried the Validate button there, but got another annoyingly unhelpful error message.



Well, the app version was still in status “Prepare to update” and I had to go in and push the “Ready to Upload Binary” button. Et voila! No error message any more on hitting Validate, but instead the selection for app and profile.

Next problem: No valid identity found, even though I was certain that I had set up code signing. I mentioned this earlier, I had forgotten to get the Installer certificate set up as well. This last step only works if you have TWO certificates set up for the app store process: Installer and App.

After getting the second certificate set up too, I still could not see it working, but after a restart Xcode picked up the installer certificate and let me upload the app. Hooray!



“… submitted to the App Store for further review” is again another part that we have met before, also called “the waiting game”.

Conclusion


Submitting apps to the Mac App Store works just like iOS apps with only very minimal differences.

  • You have 2 certificates for app store distribution: Installer and App
  • You can also have a certificate for development, though the real need for that escapes me
  • You have to register your development devices and use a development provisioning profile, probably to test things like iCloud
  • Setup for code signing is the same, though you use a different certificate to sign the app and to sign the installer package that the uploader generates for you.
  • Screenshot format is different :-)
  • You don’t submit Icon PNGs, those get pulled by iTunes from the app itself
  • The rest of the submission dialogs is identical

I did not go into Entitlements so far, as October 31st was said to be the last day before Apple said that they are going to be enforcing App Sandboxing. That in itself is a whole different world of pain, because of the way this app works with Xcode projects.