How to Program iPhone Apps from Scratch for iOS 7 – Kickstarter

Here’s my first Kickstarter project, called How to Program iPhone Apps from Scratch, which is designed to teach you iOS 6 and iOS 7 app development.

When I started programming for iPhone, it was frustrating because there was a lack of resources. Now there’s too many resources and most of them are out of date. It’s hard to find working code for iOS 6, and it’s going to be harder to follow tutorials with the upcoming Xcode 5 and iOS 7. Anytime Apple updates things, it makes our lives easier, but it also makes many of the previous tutorials wrong.

My plan is to build five courses that teach you with video tutorials and programming challenges. I’ll be creating video solutions for the challenges, so that when you’re stuck you can see how to approach a problem. All of the source code will be available for the lessons and challenges. I think a common code-base on github.com is the right thing to do, so that the lesson code can stay current.

Please help fund my project on Kickstarter so that you can learn how to make iPhone apps. You’ll help support the creation of this new set of course materials.

Learn How to Build iPhone Apps Online

I’m teaching an online iPhone Development class through Skillshare.com where you will learn how to build iPhone apps. It starts on January 28th for three weeks. All the videos are recorded, so it’s ok to miss class.

The course is designed for non-programmers and beginner developers who are struggling to learn iPhone app development on their own. I will start with the basics of C and Objective-C programming, Xcode, and move onto basic app design with Interface Builder. The class is three weeks long and will show how to think and make a complete app.

Register for Live iPhone Class

Signup today for the class if you have ideas but don’t know how to execute on them.

Project Based Learning

I wanted to keep the class focused, so I designed it to be project based. I will be creating a full app in three weeks and will provide all the source code and assets. You can choose to customize the code I provide, or start your own project in parallel.

Mat Border Calculator

Build iPhone Apps Online - Mat Border Project

The app is a utility app for artists and photographers that frame prints and have to cut mat boards. Speaking from experience, it’s a lot of work to cut out mat boards that protect and style the art in a frame. I want to reduce the complexity from a math and visualization standpoint.

Often times I don’t know how the image will look best in the frame. Should I use a 2 inch border on all edges, or should I have 4 inches on the bottom to lift the photo up?

It’s pretty easy to make an app that can do these simple math calculations and show us how the art will look using some computer graphics.

The Mat Border Calculator app solves two problems.
  1. When you’re in the zone framing, you want to focus on cutting straight, not math. This app removes the need to do math calculations in your head or on paper.
  2. Not everyone can visualize what different border widths will look like. Sometimes you might even cut multiple mat board windows just to see what looks good. This app allows easy layout previews using gestures and removes re-work.

Resources for Building iPhone Apps

I also have a beginners blog and newsletter with tips on iPhone development, marketing, downloads, and chart ranking.

Resource Bundles for iPhone Frameworks and Static Libraries

I decided to experiment with iOS Framework Guide from jverkoey’s github. There were a couple of issues that aren’t fixed for Xcode 4.5.2. It looks like some things may have changed.

Static Library Target – Framework

The last lines of the script need to be updated for the static library:

# The -a ensures that the headers maintain the source modification date so that we don’t constantly

# cause propagating rebuilds of files that import these headers.

/bin/cp -a “${TARGET_BUILD_DIR}/include/${PRODUCT_NAME}””${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers”

Resource Bundle

There are no bundle templates for iPhone, so you’ll need to start with a Mac template and adjust it for the phone.

1. Select Architectures, Base SDK, and Build Active Architecture Only, and then press delete. Pressing delete should change these settings from Mac to iPhone settings.

2. Change the Build Setting: COMBINE_HIDPI_IMAGES to NO

If you don’t change this setting, the retina graphics will be turned into TIFF files. You won’t be able to load any @2x resources if this happens.

3. Change the Product Name to match your static library’s name.

Example UIImage Loading from Bundle

    UIImage *image = [UIImageimageNamed:@"testlibrary.bundle/CloseButton@2x.png"];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

    imageView.center = CGPointMake(200, 300);

    [self.view addSubview:imageView];

Sample Code on Github.com

Checkout the demo on github.

Mocking a UIKit Delegate Protocol with Kiwi

I’m experimenting with mock objects in Kiwi and decided to try and mock the UIAlertViewDelegate. I ran into two issues.

1. Order is important when creating the mock delegate object. It needs to be setup with all the delegate method receive calls before you use the object associated with the delegate protocol.

2.  The delegate protocol methods need to be mocked in the order they are invoked, or you’ll receive a test failure. This can be trial and error, if you don’t know how the delegate protocol works.

a. For each mock delegate test, I just kept running until I was able to get the mock delegate calls passing.

b. I also discovered that the didDismissWithButtonIndex and  clickedButtonAtIndex were not invoked after using the dismissWithClickedButtonIndex method call.

#import "Kiwi.h"
#import "PSMessages.h"
#import "PSMessageConstants.h"

SPEC_BEGIN(PSMessagesTest)

describe(@"Create an alertview", ^{
__block PSMessages *messages = nil;
beforeEach(^{
messages = [[PSMessages alloc] init];
});

NSDictionary *urlMessage = @{
@"type" : @"url",
@"url" : @"http://www.PhotoTableApp.com",
@"message" : @"Create a collage for the next holiday.",
@"title" : @"Design Collages",
@"buttons" : @[@"Yes", @"No"]
};

context(@"with a url message", ^{
__block UIAlertView *alert = nil;
beforeEach(^{
alert = [messages alertForMessage:urlMessage];
});
it(@"the cancel button is pressed", ^{
id delegateMock = [KWMock mockForProtocol:@protocol(UIAlertViewDelegate)];
alert.delegate = delegateMock;

int buttonIndex = alert.cancelButtonIndex;

[[[delegateMock shouldEventually] receive] alertViewShouldEnableFirstOtherButton:alert];
[[[delegateMock shouldEventually] receive] didPresentAlertView:alert];
[[[delegateMock shouldEventually] receive] willPresentAlertView:alert];
[[[delegateMock shouldEventually] receive] alertView:alert willDismissWithButtonIndex:buttonIndex];
[[[delegateMock shouldEventually] receive] alertView:alert willDismissWithButtonIndex:buttonIndex];

// Note: delegate methods not called for programatic UIAlertView dismiss
[[[delegateMock shouldEventually] receive] alertView:alert didDismissWithButtonIndex:buttonIndex];
[[[delegateMock shouldEventually] receive] alertView:alert clickedButtonAtIndex:buttonIndex];

// Invoke methods after the delegateMock object is setup
[alert show];
[alert dismissWithClickedButtonIndex:buttonIndex animated:NO];

});

it(@"the ok button is pressed", ^{
id delegateMock = [KWMock mockForProtocol:@protocol(UIAlertViewDelegate)];
alert.delegate = delegateMock;

int buttonIndex = alert.firstOtherButtonIndex;

[[[delegateMock shouldEventually] receive] alertViewShouldEnableFirstOtherButton:alert];
[[[delegateMock shouldEventually] receive] didPresentAlertView:alert];
[[[delegateMock shouldEventually] receive] willPresentAlertView:alert];
[[[delegateMock shouldEventually] receive] alertView:alert willDismissWithButtonIndex:buttonIndex];
[[[delegateMock shouldEventually] receive] alertView:alert willDismissWithButtonIndex:buttonIndex];

// Invoke methods after the delegateMock object is setup
[alert show];
[alert dismissWithClickedButtonIndex:buttonIndex animated:NO];

});
});

});
SPEC_END

Unit Testing Static Libraries with Kiwi for iOS Development

I’ve been playing with Kiwi and I’m trying some BDD (Behavior Driven Development) for a new static library component I wanted to build.

I began with a new Xcode project using the Static Library template, but ran into issues with the difference between “logic tests” and “application tests”. In short, all my non-UIKit code worked great, until I started to test my UIKit related functions.

The code crashed and makes it frustrating to write unit tests. If you’ve never experienced it before, it’ll make your unit test experience unproductive. To solve the issue you’ll need to create a new target (empty iOS application) and include unit tests. Xcode will automagically setup the unit tests to be “Application Tests” instead of “logic tests.”

EmptyApp

#0 0x00a40881 in __HALT ()
#1 0x0097a971 in _CFRuntimeCreateInstance ()
#2 0x01337cc1 in GSFontCreateWithName ()
#3 0x05c32281 in UINewFont ()
#4 0x05c323ec in +[UIFont systemFontOfSize:traits:] ()
#5 0x05c32438 in +[UIFont systemFontOfSize:] ()
#6 0x05be24ee in +[UILabel defaultFont] ()
#7 0x05be32e5 in -[UILabel _commonInit] ()
#8 0x05be3424 in -[UILabel initWithFrame:] ()
#9 0x05e7cc67 in -[UIAlertView(Private) _createTitleLabelIfNeeded] ()
#10 0x05e8b4b9 in -[UIAlertView setTitle:] ()
#11 0x05e8bb37 in -[UIAlertView initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:] ()
#12 0×02605831 in __block_global_23 at /Users/paulsolt/dev/Photo-Slide-Show/PSMessages/PSMessagesTests/PSMessagesTest.m:165
#13 0x0261b584 in __25-[KWExample visitItNode:]_block_invoke_0 at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWExample.m:220
#14 0x0261a11e in __42-[KWContextNode performExample:withBlock:]_block_invoke_0 at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:116
#15 0x0261a11e in __42-[KWContextNode performExample:withBlock:]_block_invoke_0 at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:116
#16 0x0261a11e in __42-[KWContextNode performExample:withBlock:]_block_invoke_0 at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:116
#17 0x0261a03e in -[KWContextNode performExample:withBlock:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:132
#18 0x0261a05d in -[KWContextNode performExample:withBlock:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:135
#19 0x0261a05d in -[KWContextNode performExample:withBlock:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWContextNode.m:135
#20 0x0261b539 in -[KWExample visitItNode:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWExample.m:216
#21 0x0261a553 in -[KWItNode acceptExampleNodeVisitor:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWItNode.m:41
#22 0x0261ae22 in -[KWExample runWithDelegate:] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWExample.m:113
#23 0x02618c95 in -[KWSpec invokeTest] at /Users/paulsolt/dev/Photo-Slide-Show/Frameworks/Kiwi/Kiwi/KWSpec.m:105
#24 0x2010405b in -[SenTestCase performTest:] ()
#25 0x201037bf in -[SenTest run] ()
#26 0x2010792b in -[SenTestSuite performTest:] ()
#27 0x201037bf in -[SenTest run] ()
#28 0x2010792b in -[SenTestSuite performTest:] ()
#29 0x201037bf in -[SenTest run] ()
#30 0x201063ec in +[SenTestProbe runTests:] ()
#31 0x0072f5c8 in +[NSObject performSelector:withObject:] ()
#32 0×00002342 in ___lldb_unnamed_function11$$otest ()
#33 0x000025ef in ___lldb_unnamed_function13$$otest ()
#34 0x0000268c in ___lldb_unnamed_function14$$otest ()
#35 0×00002001 in ___lldb_unnamed_function4$$otest ()
#36 0x00001f71 in ___lldb_unnamed_function1$$otest ()

Solution

1. Add a new target with it’s own unit tests. Creating unit tests with a “static library” template gives you “logic tests”, while creating unit tests with a “iPhone application” gives you “application tests.” The difference is that you can’t use UIKit classes in logic tests, but you can in application tests.

EmptyApp

2. In an application test, the runloop of the iPhone app starts, which means all the UIKit goodies are setup. The bad news is that it loads all the default state from your previous app runs. You might need to write some methods to cleanup or reset state. (GHUnit is nice because it’s more sandboxed)

3. If you’re using Kiwi you’ll have to setup the Kiwi environment (library/header paths) again for the application tests.

ApplicationUnitTest

UICollectionView Custom Actions and UIMenuController

Updated for iOS 7.0 on 10-3-2013. See my StackOverflow post for additional details. In iOS 7.0, a delegate method is required because the method call is sent to the cell as the firstResponder, rather than the UIViewController. It might be a bug, or it’s a change in behavior.

The UICollectionView can provide a special UIMenuController with cut, copy, and paste actions. To add UICollectionView custom actions you need to implement a few extra methods for the shared UIMenuController object. The view controller’s parent window needs to be the key window and you’ll need to respond to UIResponder method canBecomeFirstResponder.

Continue reading

Linking to a Facebook Page from an iOS App

The Facebook app broke the old way of creating an iOS facebook page link. If the app isn’t installed the old facebook link works, but when it is installed it just opens the Facebook app to the default page.

Fix your app links to Facebook using this url format:

Continue reading

Duplicate Code Signing on Xcode with Any iOS SDK

Working with Xcode code signing is a pain. You may have encountered a situation where there are more than two code signing identity’s in Xcode. This means that you potentially have to change four different code signing settings to update your app, rather than just two.

I think this is cruft from upgrading to the newest Xcode version or something. Here’s what it looks like and here’s how to fix it. It’s very annoying when developing and testing with adhoc and app store builds.

 

Code signing in Xcode 4

 

The issue is visible with the “Any iOS SDK” seen as a subitem to the Debug and the Release builds. Things won’t work correctly if the two don’t match in my experience. So I end up having to change two at a time.

Solution

You can close Xcode or keep it open. It seems to work either way before you start the next steps.

1.Open your project folder in finder. (Right click project in Xcode and choose “Show in Finder”)

Show in finder

2. Right click on the Xcode project file in Finder -> “Show Package Contents”

Xcode project Show package contents

3. Right click on the project.pbxproj and choose “Open With” -> “TextEdit”

Xcode project in Textedit

4. Search for “Sign” and delete any lines that look like the following. Xcode will regenerate, so don’t worry about deleting them. I believe the first two are the root of the problem.

“CODE_SIGN_IDENTITY[sdk=iphoneos*]” = “iPhone Developer”;

“CODE_SIGN_IDENTITY[sdk=iphoneos*]” = “iPhone Developer”;

CODE_SIGN_IDENTITY = “iPhone Developer”;

Textedit code sign identity

5. Open the project settings in Xcode and see the duplicate “Any iOS SDK” are removed and Xcode regenerated the default Code Sign Identities.

Fixed code sign duplicates

6. Update with your credentials for Debug/Release.

Update code sign

Enjoy.

Leap Motion – Control your Mouse on Mac OSX

I have a development kit for Leap Motion that arrived last week and I’ve been working on an Objective-C/C++ wrapper for the C++ Leap Motion SDK. I used opaque pointers to contain the Objective-C/C++ code into one file so that the header can be included in vanilla Objective-C apps.

Now that I have a starting point I’m working with the data from Leap Motion. My first goal is to make a functional mouse counterpart that can be used “hands free.” Here’s a video of my of basic mouse control. I use the position and direction of the finger to cast a ray into the monitor (ray tracing anyone?). Using the intersection point and a lot of math you can start to translate the raw leap data into something meaningful for an application.

Going further I’m investigating the best way to recognize a tap gesture and what that will look like in practice.

Using the social.framework on iOS 6.0

Using the social.framework is real simple on iOS 6.0. Apple only refers to their reference, so I decided to show the code snippet example. To change between twitter and  Sina Weibo, just use the types: SLServiceTypeSinaWeibo SLServiceTypeTwitter. It just takes 10 lines of code.

If you used the Twitter.framework, you can remove it and replace your Twitter code with the following code. The Social.framework will manage all social networks moving forward.

if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {

SLComposeViewController *socialSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];

[socialSheet setInitialText:@"posted from @PhotoTable"];

[socialSheet addImage:image];

[socialSheet setCompletionHandler:^(SLComposeViewControllerResult result) {

NSLog(@"Result: %d", result);

}];

[self presentViewController:socialSheet animated:YES completion:^ {

}];

}

© 2014 Paul Solt

Theme by Anders NorenUp ↑