Solution: Apple TV 3 and the spinner, plus the failure of AirPlay Screen Mirroring

apple_tv-q410-angled-lgI got an new Apple TV (3rd generation hockey puck), and I was watching a movie downloaded from iTunes. An hour and a half in, WHAMO, seized up. After going through reading an encyclopedia of posts, I took the extreme of shutting down my Macbook Pro AND my Apple TV. That worked for the next hour.

In addition, my Airplay screen mirroring did not work either. I have all new hardware, all new software….what gives? I had three clues: 1) 1 hour, 2) AirPlay mirroring never worked, 3) a router that gets hammered by the neighbors.

More reading, until I found a comment about connections and the ATV going to sleep.

So, I decided to go to the Apple TV Settings -> General, and changed Sleep After from 1 hour to Never. All of a sudden, restarting the movie went perfect, noticeably quicker. For fun, I tried AirPlay mirroring, and it also worked perfectly.

I’m not planning on leaving the Apple TV on all the time. I’m not saying this is a “fix.” I’m just posting that this was a simple solution that worked. If this fails me later, I’ll post again. Otherwise, if you find this post, and no update, give it a shot, it takes 10 seconds, no rebooting.

Posted in Apple Tagged , ,

Xcode – Renaming Repository Bug Using Git, Pull From Project

I’m using xCode 4.5.2, and was checking out some of my projects from Git, as I now have a new Retina Macbook Pro. I was beset by two problems.

When I went to check out a repository, the Folder names were right, but the name in the Organizer list was wrong. It picked a previous project name/repository name. Very frustrating, rebooting does not help.

I figured out a way to trick it, and got it to work. Here are the steps:

1) Go to the Organizer, and when you add, choose Add Repository

2) Now you do as you would the Checkout, only now you control the name.

3) Now you’ll have a repository with the right name, but no project. On the bottom left you can now do a Pull.

4) Once the Pull completes, Xcode make a new repository name, with the correct name this time. You can now just delete the generic repository if you’d like.

Note: I know some people just do the repository and start pulling, especially with the command line, and they don’t care if they pull every project down. That takes up a lot of disk space, so that’s why I’m pulling one repo/project set at a time.

My second issue was that committing only commits to the local Git, not the master. When in Organizer, there is no indicator to push. The only way I can get back to the master (as of this version) is to have the project open, and use the menus. File -> Source Control -> Commit and File -> Source Control -> Pull. That actually works.

I hope these things get tightened up in future version of Xcode.

 

Posted in Apple, iOS, Mac

iOS Tutorial: Editing TableViews

This tutorial picks up where our last tutorial on TableView Basics left off. Now that we have one, it’s time to start editing, deleting and moving things around. Again, we’ll have our starter project and our completed project downloads. For additional reading, you can check out the Apple guides on this.

First off, we can lose the button off the cell. Go to the storyboard and delete it. Move our label to the right a little bit, because we will need room for editing buttons later. Delete the button code we had in the delegate method in RootViewController.m:

– (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@”tvcItems”];

UILabel *lblName = (UILabel *)[cell viewWithTag:100];

[lblName setText:[maTheData objectAtIndex: [indexPath row]]];

return cell;

}

 

Editing Mode

To do editing, you place the table view in editing mode, which is done through another UITableView delegate method:

– (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {[tableView setEditing:YES animated:YES];

}

 

Run the project, and select any row. You should see delete buttons for each row. We can try to delete all we want, but nothing will happen until we use another delegate method

Deleting

The default editing style of any cell is deleting, so we’ll start with that. Let’s add a new UITableView delegate method.

– (void)tableView: (UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath: (NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {

// Delete the row from the data source

[maTheData removeObjectAtIndex:[indexPath row]];

// Delete row using the cool literal version of [NSArray arrayWithObject:indexPath]

[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

}

}

 

There are three important steps, identify the edit type, update the datasource array, then update the table view. Run the project, and delete away!

Inserting

Inserting is just doing the opposite, and of course, we need another delegate method. Alter RootViewController.m to the following:

– (UITableViewCellEditingStyle)tableView: (UITableView *)tableView editingStyleForRowAtIndexPath: (NSIndexPath *)indexPath {
// conditional for inserting
return UITableViewCellEditingStyleInsert;// conditional for deleting

//return UITableViewCellEditingStyleDelete;

}

 

– (void)tableView: (UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath: (NSIndexPath *)indexPath

{

if (editingStyle == UITableViewCellEditingStyleDelete) {

// Delete the row from the data source

[maTheData removeObjectAtIndex:[indexPath row]];

// Delete row using the cool literal version of [NSArray arrayWithObject:indexPath]

[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

}

else if (editingStyle == UITableViewCellEditingStyleInsert) {

//

Insert something into the array, and you can just add a populated NSIndexPath of data or simplr reload data

[maTheData addObject:@”I’m a new item!”];

[tableView reloadData];

}

}

 

Run the project and start adding. Real world projects typical use an add button and some kind of modal to add whatever you want to add to the data. Usually it’s a simple append, or it may get resorted. The best use of UITableViewCellEditingStyleInsert is if you want to insert data in between two particular rows. The point here is just to show the insert edit mode in action. To change it back to delete, simply comment out the entire

editingStyleForRowAtIndexPath method.

Moving

Another typical editing type is moving data around the list to reorder the items. To enable moving, we’ll add two more UITableView delegate methods.  Here’s the code:

– (BOOL)tableView: (UITableView *)tableView canMoveRowAtIndexPath: (NSIndexPath *)indexPath {
return YES;}

 

First, we end up in edit mode by selecting the cell. The default for moving is NO, so we want to return YES instead. The moving of the items in the table view will happen on its own. However, we must update our datasource to show the reorder.

 

– (void)tableView: (UITableView *)tableView moveRowAtIndexPath: (NSIndexPath *)fromIndexPath toIndexPath: (NSIndexPath *)toIndexPath{
NSString *mover = [maTheData objectAtIndex:[fromIndexPath row]];[maTheData removeObjectAtIndex:[fromIndexPath row]];

[maTheData insertObject:mover atIndex:[toIndexPath row]];

 

[tableView setEditing:NO animated:YES];

 

}

 

Notice we get a copy of the data in our array being moved, delete the object from the array, and insert the copy back into the array. Again we take ourselves out of editing mode at the end of the move. It is common to instead just stay in an edit mode and do many steps and have a “Done” button to stop editing. This method usually has a table view reload. It’s your choice. In our example, if you want to see the data changes, simply put a breakpoint in the

moveRowAtIndexPath method and observe the array.

Run the project. Once a cell is selected, the cell will show the drag handle on the far right of the cell. Hold this handle, and in a moment it will pop up slightly.

Conclusion

In order to edit a table view, simply put the table in editing mode. Then use the appropriate combination or UITableView delegate methods to control the editing.

Posted in Apple, iOS

iOS Tutorial: Basics of Table Views and Prototype Cells in Storyboards

In this tutorial, we’ll go over the basics of populating tableviews with data, and using the prototype cells introduced in iOS 5. Many of the samples online have very complicated navigation controller code. Instead, we want to just do the very basics of a UITableView and UITableViewCell. No nav bar, no master/detail navigation. We’re also not going to try to tackle Core Data here. We’re also not worried about saving our changes. We’re just trying to understand tables and cells.

First, we have two projects to download, the starter project, and the completed project. In the starter project, we’ve made a new project, added a Table View Controller in our storyboard, and deleted the View Controller. We also have deleted the ViewController.h/.m set that is made automatically, and created a new file, calling it RootViewController, which is a UITableViewController. We’ve also hooked this new file set to our Table View Controller in our storyboard.

Becoming a Delegate

The first step is to work with the UITableViewController, so that when the table view is being created, we populate it with data. We also want to keep the data in sync with what’s in the table. This means we sign up for two protocols in RootViewController.h:

@interface RootViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>

 

Creating Data

For this tutorial, we’re just going to use an array. In a real project, it’s typical that you would connect to a web service and grab a data structure, like XML or JSON. Declare an array in RootViewController.h:

@property (strong, nonatomic) NSMutableArray *maTheData;

 

Now let’s implement it in RootViewController.m, we’ll synthesis our array, and build it when we load:

@implementation RootViewController@synthesize maTheData;

– (void)viewDidLoad
{
[super viewDidLoad];
if (!maTheData) {
maTheData = [[NSMutableArray alloc] initWithObjects:@”Comets”, @”Asteroids”, @”Moons”, nil];
}
}

 

Implementing Table View Delegate Methods

Now we have some work to do to populate our table. The way we do this is by setting data at different parts of the table as it is built row by row. First, we need to identify the number of sections the table needs. If this is zero, nothing will ever appear. In our case, it’s just one.

– (NSInteger)numberOfSectionsInTableView: (UITableView *)tableView
{
return 1;
}

 

Next, we need to identify the number of rows we need in the section, which is the number of items in the array.

– (NSInteger)tableView: (UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [maTheData count];
}

 

Storyboard Connections

Time to go to the storyboard, and select the Table View. Ctrl-drag back to the RootViewController. We want to connect it back to the controller to ensure both the delegate AND the datasource are connected to the controller class. This ensures the delegate calls will fire, and the data will we synced. If you skip this step, you won’t see anything in your cells.

Prototype Cells

Cell designs that are reused, are very performant, as opposed to cells that are completely different, row to row. Many apps use the standard cell types, basic, right detail, left detail, subtitle. But you may have an app with custom cells with more information or purpose. This is where prototype cells have make the process a lot easier than in the past. Prototype cells in a storyboard allow you to create custom cells quickly. Just drag the components you want on your cell.

It is incredibly important to set your identifier for the cells, because when you get to the delegate methods, you need to indicate the cells’ class. This provides the access to put the data on the cell itself. From the storyboard, select the one table view cell, which is a child of the table view, and go to the Attributes Inspector. Under Identifier, type “tvcItems”.

Select the cell, still in the Attributes Inspector. The first item is Style. Choose Basic. Now the cell has a label that’s been added automatically. Farther down in the view section is Tag, type “100.” The number does not matter, a much as the fact that each object on the cell should have a unique tag. If you don’t use the tag, the data will not appear later.

Populating Cells

Using the combination of the cell identifier and the tag, we will have full access to deliver the data to the cell. Back to RootViewController.m, add:

– (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@”tvcItems”];
UILabel *lblName = (UILabel *)[cell viewWithTag:100];
[lblName setText:[maTheData objectAtIndex:[indexPath row]]];
return cell;
}

 

Run the project in the simulator, and you should see a simple table view with our array data.

Custom Cells

Whether you use one of the custom table view cell style types or go custom, the process is the same. However, with custom, you must drag all the objects you want on the cell manually. Go to the storyboard and select the cell. Change the style to Custom. The first thing you’ll notice is our label is gone. Grab one and drag it onto the cell, and set its Tag to 100. Now grab a Round Rect Button and drag it onto the cell, and set it’s Tag to 200. The Tag is in the View section, so you will have to scroll down a bit to find it, but it’s there. You may want to manually make them wider, so the text will fit easily.

Now go back to RootViewController.m, and add to the cellForRowAtIndexPath method to:

– (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@”tvcItems”];
UILabel *lblName = (UILabel *)[cell viewWithTag:100];
[lblName setText:[maTheData objectAtIndex:[indexPath row]]];
UIButton *btnName = (UIButton *)[cell viewWithTag:200];
[btnName setTitle:[maTheData objectAtIndex:[indexPath row]] forState:UIControlStateNormal];
return cell;
}

 

Run it again in the simulator, and the buttons should have the same text from the array. While this may not seem terribly useful, it shows the basics of customization. A real project would typically have complex sets of data, including images and multiple labels. For each object type, drag it, tag it, make a local method variable of the object type, and set the data to it.

Conclusion

The addition of storyboards and prototype cells has made the old way of populating tables much easier than before. The process is to become a delegate, have some data available, set the delegate and datasource from the table to the controller, set the identifier for the cell, set the tags of the cell objects, and implement the delegate methods.

Posted in iOS

iOS Tutorial: Combining Delegation, Storyboards, Popovers and Data

In this tutorial, we’ll show how to pass data from a view controller to a popover, and have data passed passed back from a button click, as well as dismissing the popover. The benefit is that it allows you to programmatically save or alter data, and pass it back. This is in contrast to a popover being dismissed by merely tapping outside the popover area of the screen. These are typical elements that would be used together for an iPad or Universal project. Since popovers are not available to iPhone (as of iOS 6 anyway), this would be used with an iPad storyboard.

I’ve posted the project files for starting, and the completed final.

Starting Point

The project starts with an iPad storyboard. The initial view controller is a UIViewController called RootViewController. It already has connected IBOutlets for a UITextField and a UIButton. There is a another UIViewController called PopViewController, which is the popover. A segue has been created from the button in the RootViewController to PopViewController. There is a UITextField and a UIButton on the popover to send back to the root, which are connected outlets. The view controller class files have been created and connected in the storyboard.

Segue Identifiers

It’s important to always give a name to your segues, as it is common for one view controller to have multiple segues. When doing segue delegation, you want to manage which segue, and differentiate which code goes with what segue. In the storyboard, select your segue, and go to the Attributes Inspector. Name the segue “segPop.”

Setting IBActions

The first thing we want to do is create IBActions for the buttons. In PopViewController.h, add a new function at the bottom.

@property (strong, nonatomic) IBOutlet UITextField *tfNewData;

– (IBAction)goBack: (id)sender;

@end

In PopViewController.m, we want to add the implementation of the function.

– (IBAction)goBack: (id)sender {

}

@end

 

 

Now connect the button click to the IBAction. One way to do this is to go to the storyboard, select the button in the Document outline, and ctrl-drag to Pop View Controller. Select the inaction goBack.

You can always go to the Connections Inspector to see (or set) your connections.

Delegation

Delegation is a programming pattern that allows an object to work in coordination with another object. A delegate will receive event messages, or callbacks, from the delegating object. Using delegation is so common in iOS development, that understanding it is a requirement.

Creating a Protocol

In order to do a delegate callback function, you need to establish a protocol, which will outline what callbacks are available. In PopViewController.h, add some protocol lines.

#import <UIKit/UIKit.h>@protocol PopViewControllerDelegate;    // Declare a protocol name

@interface PopViewController : UIViewController

@end

@protocol PopViewControllerDelegate <NSObject>

@required

– (void)dismissPop: (NSString *)value;

@end

 

It is good practice to name your delegate as “<classname>Delegate”, making it easy to understand to code. In protocols, methods can be required or optional. If your class implements a delegate protocol, and does not include a method to handle the callback, Xcode will give a warning that the implementation is incomplete.

Creating a Local Delegate

The calling object needs to set itself as the delegate in the delegation relationship. We’ll establish a property to hold this. Back to PopViewController.h:

@property (weak) id <PopViewControllerDelegate> delegate;

 

The property is set to a weak reference, for ARC compliance, and good memory management. Because this property stores a reference from a different class instance, if t gets destroyed somewhere else, this instance can free the memory. Make sure to synthesize any properties you add, so in PopViewController.m:

@synthesize delegate;

 

Sending a Delegate Method

Now that we have a property to store the delegate, we can add the code to send a delegate event. We’ll do that in our IBAction of the button in the popover. Add a line to our goBack function in PopViewController.m:

– (IBAction)goBack: (id)sender {

[delegate dismissPop:[tfNewData text]];  // make delegate callback here

}

 

This code is going to take the text of our UITextField and send it back to the delegate, which is our RootViewController. Remember that delegate is an id, or pointer, back to the RootViewController instance. This tells us where to send the delegate message.

Preparing for Incoming Data

In order to prepare to receive data from RootViewController, we want to add a string property to receive the data, as the segue will not have direct access to the UITextField. In PopViewController.h, add the following:

@property (strong, nonatomic) NSString *strPassedValue;

 

Make sure to synthesize in PopViewController.m:

@synthesize strPassedValue;

 

Since PopViewController is a UIViewController, it is automatically able to do its own delegate methods. We want to add one to PopViewController.m:

– (void)viewWillAppear: (BOOL)animated {
[tfNewData setText:strPassedValue];
}

 

Becoming a Delegate

Go to RootViewController.h, and add the following:

#import “PopViewController.h”   // add header to gain access to its protocol
@interface RootViewController : UIViewController <PopViewControllerDelegate, UIPopoverControllerDelegate>

 

First, you must import the header file, which is how to reach the delegate protocol. This will help code completion make this easy. We want to be sign up for two delegate protocols. The second one is so we can receive callback messages from the popover. Second, we have an implementation in RootViewController.m to receive the callback:

– (void)dismissPop: (NSString *)value {

[tfUserText setText:value]; // populates data from popover

}

 

This function allows us to capture and display the data string sent back from the popover via delegation.

Managing the Popover

We want to be able to send data to our popover, as well as be able to programmatically close our popover, so in RootViewController.h, add some properties:

@property (strong, nonatomic) UIStoryboardPopoverSegue *currentPopoverSegue;
@property (strong, nonatomic) PopViewController *pvc;

 

Synthesize them in our implementation RootViewController.m:

@synthesize currentPopoverSegue;
@synthesize pvc;

 

Passing Data in a Segue

Since we signed up for the popover delegate protocol, we want to implement the prepareForSegue function. Add the lines:

-(void)prepareForSegue: (UIStoryboardSegue *)segue sender: (id)sender {
if ([[segue identifier] isEqualToString:@”segPop”]) {
currentPopoverSegue = (UIStoryboardPopoverSegue *)segue;
pvc = [segue destinationViewController];
[pvc setDelegate:self];
[pvc setStrPassedValue:[tfUserText text]];}

}

 

In this code, we are looking to make sure that we have the proper segue, which is why we set its identifier property in the storyboard. Next, we want to keep a pointer to the popover segue, so we can dismiss it after we have processed the delegate callback data. We also want a pointer to the view controller that is the popover, because we set ourselves as the delegate. Without setting the delegate, the delegate callbacks would go nowhere. Lastly, we want to pass data into the PopViewController,which allows us a round trip of data back and forth from both objects.

Dismissing the Popover

As the final step, we want to add a line of code to our delegate callback function in RootViewController.m:

– (void)dismissPop: (NSString *)value {
[tfUserText setText:value]; // populates data from popover
[[currentPopoverSegue popoverController] dismissPopoverAnimated: YES]; // dismiss the popover
}

 

The final line uses our pointer to the segue, so we can have the popoverController dismiss or popover instance. Notice we do not send anything to the PopViewController instance. When we created a segue that was of type popover, a popoverController was automatically created for us, and that is what want to access to do the actual dismissing.

Using Data Passed via Segue

Now that we have data coming across the segue, we want to use it in our popover. In PopViewController.h, we want to add  In PopViewController.m, add the following UIViewController delegate function:

– (void)viewWillAppear: (BOOL)animated {
[tfNewData setText:strPassedValue];
}

 

Conclusion

Run the project in the iPad Simulator, and you should be able to pass data back and forth between the text fields. The button on the popover should also dismiss the popover. Okay that was a lot of steps, but you can pass data from segues, delegate callbacks, and control your popovers, all at the same time.

Posted in Apple, iOS

Illustrator CS6 and HTML5: Creating Dynamic Vector Web Content (SVG)

I thought I would post a download link for my user group presentation on dynamic SVGs. In the download, I’ve included source code, Illustrator files, and presentation slides.

I’ll have to post an extensive description of what is going on in these samples. It’s probably going to be several posts. I’ve been unhappy with a lot of the samples I have seen out there for SVG. I’ve collected some good samples, that still work (most do NOT work, because they are too old), and some of my own. These samples show a variety of methods to achieve similar results, using different combinations of SVG, CSS, and Javascript.

Posted in Adobe, CSS, HTML5 Tagged , , , , , , , ,

Product Review: CSS Hat – Generating CSS3 from Photoshop layers

CSS Hat is a Photoshop plugin that does something wonderful. It takes effects from a layer, and converts them to CSS3. If you are a Photoshop person, who never does web, why would you care? Because you probably have to give images to someone actually doing the web site. Because you’ve probably been asked to skin components, like buttons. Because it has to look good on mobile devices, especially an iPad. You need to take a serious look at CSS Hat.

The typical workflow is to create raster images, and someone else does some CSS magic (hopefully). Now imagine doing those things, only they are scalable, without needing an SVG, and they are rendered with CSS3, that you provide, but didn’t write. This is  CSS Hat. There are no image file links to mess up. The browser is rendering cached CSS, rather than cached images. So, you have speed, less file management, and when people touch/zoom your page, everything looks nice and crisp. That’s a better mousetrap.

Playing with the basics

After installing on my CS6, I decided to start playing with primitives, basic vector shapes. I created a single layer with a lazy circle, and added a simple drop shadow effect on the layer. It’s important to note that while the default blending is set to multiply, I needed to change it to normal. If you have effects that aren’t supported, the CSS Hat code window will tell you. You can add Mozilla, height/width, and also name the CSS class as your layer name. Very nice. The result is the shape and it’s shadow effect in pure CSS3!

I love the Copy to Clipboard button in the plugin. Jumping into Dreamweaver (or any web editor of your choice), I made a simple html file with a <div>, and a class. For time’s sake, I just added the style in the header. And voila! I had my shape and my shadow, no images.

There are a number of effects that are supported, though not all (no surprise). I was able to successfully combine multiple effects, including some crazy gradient overlays too gaudy to post. The point is that I had the power to use my Photoshop imagination, and transfer it to pure CSS. That’s a really big deal. This took very little time.

Support

Being a developer, I can do some crazy things even a designer would’t necessarily try, like using inner and outer stroke effects, as opposed to changing the primitive property. Why? Because all those properties will not get converted to CSS. The plugin works on the effects. Software is not a perfect thing, and sometimes there are bugs. I found some, but nothing to remotely dampen my enthusiasm. As a Photoshop user, you know there are many ways to do an effect, and I was able to work around things. I also know I can use multiple layers in html, just as I can in Photoshop.

So I sent some sample files to support, because it’s always good to help the developers out. This also allows me to gauge the support response. I’m happy to say it was right away, and some fixes are coming. I’m really happy with their response, very knowledgeable and enthusiastic. A great sign.

Conclusion

Any Photoshop designer who does anything for the web should have this plugin. It’s a mere $19.99, and worth it. I was surprised at how well it worked. It exceeded my expectations. I’ve shown a number of colleagues, and we agree that Adobe should have done this for CS6. It’s useful, simple to understand and quick to implement. We were all impressed. If you’re still using images of shapes, effects, gradients, you need to stop it. You need to embrace CSS. CSS Hat is a real winner. It’s going to make your web pages better, and it is super easy. I highly recommend it.

 

Posted in Adobe, CSS, HTML5 Tagged , , , , ,

Product Review: PaintCode by PixelCut


I purchased a copy of PaintCode from the Mac Store in March, and have used it in a real production environment. Namely, make resolution-independent images quickly, vector-based, so they look crisp on both Retina and non-retina displays. PaintCode appeared to be a great time-saver. I am happy to say that PaintCode was wildly successful in this regard. Here’s what I experienced.

I started with version 1.0. At the time, there was no support for ARC, which meant that I had to make some adjustments, using __bridge. I sent an email to PixelCut, and got an immediate response, with direct answers to my questions, a promise for ARC, and even a sample. During that time I had already started slapping the code into a storyboard, and liked an addition class in a PaintCode sample I found from David Keegan, which created UIImages with drawing blocks. His solution was small and elegant.

I was able to use the code to create images that I assigned to button states, and various animations. This was easy, and I was very aware of the hours PaintCode had saved me. It’s not going to automatically expand it’s size for you, so you may have to go back in and click Expand/Contract to get the right sizing. If your image is inside something like a CALayer, where sizing is dynamic, you manipulate the layer, and it will expand as you expect.

The feature page from the web site spends a lot of time explaining how to use the drawing tools. This is fairly easy to understand, even if you’re not a designer. As someone who already knows how to use Adobe Illustrator, any designer would find this very simple. Many developers will find it new and moderately challenging. So, they have struck the correct balance, because their audience is likely to be developers. The app is priced for what it is: it’s not a cheap tool, and it’s not a major suite tool, it’s a serious utility.

As for the phrase “The missing bridge between programmers and graphic designers,” every time I think something can bridge the gap, I’m proved wrong. It might be more appropriate to say “For those times when your designer is AWOL and is ignoring you and your deadlines.” Just a reality check. Or perhaps, “When you aren’t going to have a designer, and you have to do you own graphics.” The tutorials seem to have this scenario covered.

The Bezier tool is quite handy, although you have to know to right-click to get handles for curvatures. There are boolean operations on selected objects, which is very handy. Gradients have a finite number of steps to them when you look at the generated code. Fortunately, you have a good enough clue on how to increase this to more steps. However, if you need a ridiculous number of steps, you’re better off looking at Illustrator and SVG exporting. I’d recommend SVGKit for that.

Conclusion

I have to say I’m impressed with PixelCut. PaintCode is a fantastic product, and hits a nice niche. The app is now at version 1.01, and it has ARC support built in, just as their email had promised. I’ve used it in a production app, and I’m sure I will use it again. That’s the sign of a useful tool. PaintCode is certainly that. I highly recommend it!

 

Posted in Apple, iOS

CocoaHeads Presentation: PaintCode Resources

Here are the assets for tonight’s presentation.

 

Posted in Apple, iOS

Particle Systems in Adobe After Effects

Thanks to everyone who came to last night’s presentation. I’m posting a PDF of my Keynote slides. The screenshots are of CS 5.5, and show how to create a floor of particles, and a twisting energy vortex. Enjoy!

Posted in Adobe Tagged , , ,