Archive for November, 2009

26 NovGood app ideas are rejected beforehand

An idea of useful iphone app took my mind for several hours. The idea is simple: notify users when there is a new refurbished product in Special Deals section of Apple Online Store.

The ideal is to push notifications to users, but this approach requires server side with a kind of spider. It’s more than a late night experiment target.

I spent a little time and made a prototype which parses products from apple.com. Of course it takes time to load html pages.

In common there may be a lot of apps with similar functionality, but you should know what Apple officially thinks about it. It will exactly violate section 3.3.7 of the iPhone SDK Agreement:

“Applications may not use any robot, spider, site search or other retrieval application or device to scrape, retrieve or index services provided by Apple or its licensors, or to collect information about users for any unauthorized purpose. ”.

There is even a real example of rejected app. But note, it’s a really useful app.

It’s strange feeling when good ideas is doomed, a little easier when it have not being developed yet.

Anyway I wish you quality ideas and dreams!

26 NovAttaching an image of UIView to email

Today I was working on GPS Speedometer and was need to attach an UIImage of MKMapview. As it has turned out it’s very easy:

- (IBAction) email{ // CREATING MAIL VIEW MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init]; controller.mailComposeDelegate = self; [controller setSubject:@"Check this route out"]; [controller setMessageBody:@"Attaching a shot of covered route." isHTML:NO];

 // MAKING A SCREENSHOT UIGraphicsBeginImageContext(_mapView.frame.size); [_mapView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

 // ATTACHING A SCREENSHOT NSData *myData = UIImagePNGRepresentation(screenshot); [controller addAttachmentData:myData mimeType:@"image/png" fileName:@"route"]; 

 // SHOWING MAIL VIEW [self presentModalViewController:controller animated:YES]; [controller release];}

That’s how it looks:

24 NovConvert objective-c typedef enum to its string equivalent

It’s small wonder that there is no standard way to get enum string description.

This is a code snippet solves the problems the easiest way:

// In a header filetypedef enum {  JSON,  XML,  Atom,  RSS} FormatType;

NSString * const FormatType_toString[];              

// In a source fileNSString * const FormatType_toString[] =
{  @"JSON",  @"XML",  @"Atom",  @"RSS"};...// To convert enum
to string:NSString *str = FormatType_toString[theEnumValue];

If you change the enum don’t forget to change the array of descriptions.

Second way is to create a mapping table. It’s more expensive in both sense

(your brain time and processor time) so i prefer the first one.

23 NovMac OSX Dock like animation for iPhone

Last evening I thought about Mac OSX vs. iPhone user interfaces. They have “family” likeness in usability and design, but there is a huge chasm also caused by iPhone Touch Approach of UI. We are on a new age starting, i think, the age where information is obtained by touches.

On this romantic note I want to stop talking and keep making things. The first thing I thought was original Mac OSX dock

and resolutely decided to simulate its animation on iPhone.

[youtube http://www.youtube.com/watch?v=7CkxxV5ocA0&hl=ru_RU&fs=1&]

I’ve chosen popular browsers’ icons for the buttons, don’t be surprised about IE, I

am quite neutral about this stuff ;)

There are some code snippets. Animations of activating/deactivating buttons:

#define CONST_animation_time 0.2#define CONST_enlarge_proportion 1.3

- (IBAction) activate:(UIView*)view{  CGContextRef context
= UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil
 context:context]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
 [UIView setAnimationDuration:CONST_animation_time];
[view setCenter:UpPointOfView(view)];    

 CABasicAnimation *scalingAnimation =
(CABasicAnimation *)[view.layer animationForKey:@"scaling"];    

 if (!scalingAnimation) {  scalingAnimation = [CABasicAnimation
 animationWithKeyPath:@"transform"];  scalingAnimation.repeatCount=1;
  scalingAnimation.duration=CONST_animation_time;  scalingAnimation.autoreverses=NO;
 scalingAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
 scalingAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DMakeScale(1
.0, 1.0, 1.0)];  scalingAnimation.toValue=[NSValue valueWithCATransform3D:CATransform
3DMakeScale(CONST_enlarge_proportion, CONST_enlarge_proportion, 1.0)]; }

 [view.layer addAnimation:scalingAnimation forKey:@"scaling"]; view.layer.transform =
 CATransform3DMakeScale(CONST_enlarge_proportion, CONST_enlarge_proportion, 1.0);
[UIView commitAnimations];}

- (IBAction) deactivate:(UIView*)view{ CGContextRef context =
 UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:CONST_animation_time];
[view setCenter:DownPointOfView(view)];   

 CABasicAnimation *scalingAnimation =
(CABasicAnimation *)[view.layer animationForKey:@"descaling"];   

 if (!scalingAnimation) {  scalingAnimation =
[CABasicAnimation animationWithKeyPath:@"transform"];
 scalingAnimation.repeatCount=1;   scalingAnimation.
duration=CONST_animation_time;  scalingAnimation.
autoreverses=NO;  scalingAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseOut];  scalingAnimation.
fromValue=[NSValue valueWithCATransform3D:
CATransform3DMakeScale(CONST_enlarge_proportion,
CONST_enlarge_proportion, 1.0)];
 scalingAnimation.toValue=[NSValue valueWithCATransform3D
:CATransform3DMakeScale(1.0, 1.0, 1.0)]; }    

 [view.layer addAnimation:scalingAnimation forKey:@"descaling"];
 view.layer.transform =
CATransform3DMakeScale(1.0, 1.0, 1.0); [UIView commitAnimations];}     

- (BOOL) isMultipleTouchEnabled {return NO;}

UIView *activeView = nil;

- (BOOL) animateView :( UIView*)view atPoint:(CGPoint)point{ BOOL isviewActive =
([view isEqual:activeView]);

 if (Distance(view.center, point) <= 30)
{  if (!isviewActive)  {   [self activate:view];
 activeView = view;   return YES;  }
} else if (isviewActive) {  [self deactivate:view];
activeView = nil;  return YES; }     

 return NO;}

Don’t forget to add “QuartzCore.framework” to the project.

Simple algorithm decides which buttons to active.

When finger is down algorithm finds the nearest button and activates it.

A button is deactivated when another button is closer or down finger is far than 50 points:

- (UIView*) nearestViewToPoint:(CGPoint)point{ UIView *candidateView =
nil; CGFloat candidateDistance = 100000;

 for (UIView *v in [self subviews]) {  CGFloat dist = Distance(v.center, point);
 if (dist < candidateDistance)  {   candidateView = v;   candidateDistance = dist;  } }    

 return candidateView;}

- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event{ CGPoint pt =
[[touches anyObject] locationInView:self];        

 UIView *nearestView = [self neares
tViewToPoint:pt]; if
(![activeView isEqual:nearestView])
 {  [self deactivate:activeView];  activeView = nil;       

  if (Distance(nearestView.center, pt)
 <= 30)  {   [self activate:nearestView];
  activeView = nearestView;  } }
 else if (Distance(activeView.center, pt) > 50) {
 [self deactivate:activeView];  activeView = nil; }              

 [self setNeedsDisplay];}

-(void)touchesEnded:(NSSet*)touches  withEvent:(UIEvent*)event{ if (activeView) {
 [self deactivate:activeView];   activeView = nil; }}

- (void) touchesBegan:(NSSet *)
 touches withEvent:(UIEvent *) event{ if (!activeView)
 [self touchesMoved:touches withEvent:event]; }

Obviously it’s hard to apply to real project, but quite interesting as a training on animations for iPhone SDK.

Look sources here or git directly.

17 NovMap View rotation with accelerometer

Did you ask your self how that easy or difficult to rotate a map in response to a device position in space? It’s easy.

You need a MapKit and QuartzCore frameworks being added to your project. Then a small piece of math code which can be explained by several words: rotate MKMapView to necessary agnle.

I will copy full source code, because it’s very easy:

@interface MapViewRotationViewController : UIViewController { IBOutlet UIView *viewToRotate;}

@end

#import "MapViewRotationViewController.h"#import "QuartzCore/QuartzCore.h"

#define CONST_fps 25.#define CONST_map_shift 0.15

@implementation MapViewRotationViewController

- (void)viewDidLoad {    [super viewDidLoad];

 // accelerometer settings [[UIAccelerometer sharedAccelerometer] setDelegate:self]; [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / CONST_fps)];}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{ static CGFloat ZZ = 0.; CGFloat z = (atan2(acceleration.x, acceleration.y) + M_PI);

 if (fabsf(ZZ - z) > CONST_map_shift) {  viewToRotate.layer.transform = CATransform3DMakeRotation(ZZ=z, 0., 0., 1.); }}

@end

Can’t make a video now. Please catch several screenshots instead:
http://picasaweb.google.com/s/c/bin/slideshow.swf

Try to make a MKMapView Z-rotation as a home work ;)
Download source here or git directly full package.

14 NovUITableView scrolls to top with UISearchBar

Having UITableView with filtering UISegmentedControl you can simply use:

[self.tableView scrollToRowAtIndexPath:[NSIndexPath
indexPathForRow:0 inSection:0] atScrollPosition:
UITableViewScrollPositionTop animated:YES];

But it won’t help when UITableView has a UISearchBar and you want users see it before first row. In this case you should you UIScrollView(UITableView’s super class) method:

[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

13 NovUIView Jump Animation code snippet

I was need to make a jumping fruits in our Road Slot game for iPhone. Now have a minute to share an animation code snippet with you, guys.

Add QuartzCore framework to the project to use animation.

#define CONST_TIME_flying 0.8f

- (void) jumpAnimationForView:(UIView*)animatedView
toPoint:(CGPoint)point { // moving CGContextRef context =
 UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil context:context];
 [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
 [UIView setAnimationDuration:CONST_TIME_flying];
 [animatedView setCenter:point];

 // scaling CABasicAnimation *scalingAnimation =
(CABasicAnimation *)
[animatedView.layer animationForKey:@"scaling"];
if (!scalingAnimation)
 {  scalingAnimation =
[CABasicAnimation animationWithKeyPath:@"transform"];
 scalingAnimation.duration=CONST_TIME_flying/2.0f;
 scalingAnimation.autoreverses=YES;
 scalingAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseOut];
scalingAnimation.fromValue=[NSValue valueWithCATransform3D:
CATransform3DMakeScale(1.0, 1.0, 1.0)];
 scalingAnimation.toValue=[NSValue valueWithCATransform3D:
CATransform3DMakeScale(1.4, 1.4, 1.0)]; }
 [animatedView.layer addAnimation:scalingAnimation forKey:@"scaling"];
[UIView commitAnimations];}

- (IBAction) buttonPressed :( UIButton*)button{
[self jumpAnimationForView:button toPoint:
(CGPoint){rand()%320, rand()%480}];}

The UIButton simply jumps to random point on its

UIView each time you press it. That’s how it looks:

12 NovShow multiline text cells in UITableView

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section {    return 1;}

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @”Cell”;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier
:CellIdentifier];    if (cell == nil) {        cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];    }

cell.textLabel.text = @”Shakespeare’s Sonnet 1: From Fairest Creatures
We Desire Increase”; cell.detailTextLabel.text = @”We want all beautiful
creatures to reproduce themselves so…”;    return cell;}Some day everyone will need to show more than one text line in UITableViewCell. It can contain a title and a long description, but usually looks like that at the right:

f course it’d be great to switch certain UITableViewCell’s property and get the result, but it’s required to code a little to get a solution.

Firstly create a content: let’s take several Shakespeare Sonnets in Modern English:

static NSArray *titles;static NSArray *subtitles;

- (void)viewDidLoad {    [super viewDidLoad];

if (!titles)  titles = [[NSArray arrayWithObjects:
@"Shakespeare's Sonnet 1:
 From Fairest Creatures We Desire Increase",
@"Shakespeare's Sonnet 2: When Forty
Winters Shall Besiege Thy Brow", 
@"Shakespeare's Sonnet 3: Look In Thy Glass,
And Tell The Face Thous Viewest", nil] retain];
if (!subtitles)  subtitles =
[[NSArray arrayWithObjects:@"We want all
 beautiful creatures to reproduce
themselves so that beauty’s flower
will not die out; but as an old man dies in time,
 he leaves a young heir to carry on his memory.",
      @"When forty winters have attacked
your brow and wrinkled your beautiful skin,
the pride and impressiveness of your youth, so
much admired by everyone now, will be have
 become a worthless, tattered weed.",     
 @"Look in your mirror and tell the face
you see that it's time it should create another
If you do not renew yourself you would be
depriving the world, and stop some woman from
becoming a mother.",nil] retain];}

Secondly create constants for minimal width
and height of cells, for fonts of title and
 subtitle, and create get-methods for fonts,
 And method which a UITableViewCell with
 defined parameters.

#define CONST_Cell_height 44.0f#define
CONST_Cell_width 270.0f

#define CONST_textLabelFontSize    
17#define CONST_detailLabelFontSize   15

static UIFont *subFont;static UIFont *titleFont;

- (UIFont*) TitleFont;{ if (!titleFont) titleFont =
[UIFont boldSystemFontOfSize:CONST_
textLabelFontSize]; return titleFont;}

- (UIFont*) SubFont;{ if (!subFont) subFont = [UIFont
systemFontOfSize:CONST_
detailLabelFontSize]; return subFont;}

- (UITableViewCell*) CreateMultilinesCell :
(NSString*)cellIdentifier{ UITableViewCell
 *cell = [[[UITableViewCell alloc] initWithStyle:
UITableViewCellStyleSubtitle   
reuseIdentifier:cellIdentifier] autorelease];
cell.textLabel.numberOfLines = 0; cell.textLabel.font = [self TitleFont];
cell.detailTextLabel.numberOfLines = 0; cell.detailTextLabel.font =
 [self SubFont];
return cell;}

Now make a method which returns a height of cell with two input strings.
Output height
is calculated by constraining to certain size and previously defined fonts:

- (int) heightOfCellWithTitle :( NSString*)titleText
andSubtitle:(NSString*)subtitl
eText{ CGSize titleSize = {0, 0}; CGSize subtitleSize = {0, 0};

 if (titleText && ![titleText isEqualToString:@""])
titleSize = [titleText sizeWithFont:
[self TitleFont] constrainedToSize:CGSizeMake(CONST_Cell_width, 4000)         
 lineBreakMode:UILineBreakModeWordWrap];

 if (subtitleText && ![subtitleText isEqualToString:@""])   subtitleSize =
 [subtitleText
 sizeWithFont:[self SubFont]  constrainedToSize:CGSizeMake
(CONST_Cell_width, 4000)  
 lineBreakMode:UILineBreakModeWordWrap];

 return titleSize.height + subtitleSize.height;}

Lastly we need to change UITableViewController's standard methods and create
"heightForRowAtIndexPath". Number of rows and
"heightForRowAtIndexPath" depend of the content.
 "cellForRowAtIndexPath" must return our special multilined UITableViewCell.

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section
{    return MIN([titles count], [subtitles count]);}

- (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
CellIdentifier];  
  if (cell == nil) {        cell = [self CreateMultilinesCell:CellIdentifier];
    }

    cell.textLabel.text = [titles objectAtIndex:indexPath.row];
 cell.detailTextLabel.text =
 [subtitles objectAtIndex:indexPath.row];    return cell;}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath
{ NSString *title = [titles objectAtIndex:indexPath.row]; NSString *subtitle =
[subtitles objectAtIndex:indexPath.row];

 int height = 10 + [self heightOfCellWithTitle:title andSubtitle:subtitle];
 return
(height < CONST_Cell_height ? CONST_Cell_height : height);}

Now all including Shakespeare must be satisfied, because our
UITableViewController
renders sonnets with right height.

But this is just a sample solution, don't stop on it. Try to add UITableViewCell's
accessoryType or UIInterfaceOrientations and you will need to add options to
"heightOfCellWithTitle".

Also you can require to support different versions of SDK, it also kind of
challenge and a topic for separate post. Just ask for and you will get it.

Please load sources from GitHub or git directrly
 "git clone git://github.com/slatvick/Alterplay-iPhone-dev-tips.git".

O

Now all including Shakespeare must be satisfied, because our UITableViewController renders sonnets with right height.

But this is just a sample solution, don’t stop on it. Try to add UITableViewCell’s accessoryType or UIInterfaceOrientations and you will need to add options to “heightOfCellWithTitle”.

Also you can require to support different versions of SDK, it also kind of challenge and a topic for separate post. Just ask for and you will get it.

Please load sources from GitHub or git directrly “git clone git://github.com/slatvick/Alterplay-iPhone-dev-tips.git“.

08 NoviPhone app design templates for hand drawing

There are too much tools for designing next iPhone top application. Think i’ll make a special post for best of them.

Today I want to share my templates which are used in everyday work. First two are simple and linear. They have wide screens and I usually use them to paint look detail.

Next pair have more screens on a sheet, but they are smaller and composite of vertical and horizontal. Use them to draw more common things without details.

The last one is useful to draw most common ideas and show crossing form one view to another. It’s not necessary to draw original GUI elements, you can just specify title or small descriptions on that.

Download or print these design templates from Google docs.

This original iPhone Wireframe Photoshop Template was used to make composites. Thank, Neil.

07 NovSource snippets from Alarm like iPhone application

Today I made a very simple alarm like application. It’s my friend’s request.

He wanted a mobile app that can ONLY time a certain period.

In contrast to built-in iPhone Timer it must NOT to show how much time past from begin and simply plays random song from the iPod when the time is up. Unusually? Agreed. Nothing must distract friends’ minds while meditations ;)

While coding this helpful utility I used several new APIs of iPhone SDK 3.0 (3.1.2). Catch some source snippets.

So my friend wants to hear nothing while meditation and to be waked up by a random song from iPod library. Do mute playing music at the start:

if ([[MPMusicPlayerController iPodMusicPlayer] playbackState]
== MPMusicPlaybackStatePlaying)  [[MPMusicPlayerController iPodMusicPlayer] pause];

make a vibration and keep playing at the end:

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)if ([[MPMusicPlayerController iPodMusicPlayer] playbackState]
== MPMusicPlaybackStateStopped) {  [[MPMusicPlayerController
iPodMusicPlayer] setShuffleMode:MPMusicShuffleModeSongs];
 [[MPMusicPlayerController iPodMusicPlayer]
 setQueueWithQuery: [MPMediaQuery songsQuery]];
}  [[MPMusicPlayerController iPodMusicPlayer] play];

To increase iPhone battery life we must turn on the proximity sensor which

monitors if there is something very close and make a screen dim if necessary.

Put your device downscreen and it dims. iPhone autolocking must be turn off.

[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
/ / disable autolocking [[UIDevice currentDevice]
setProximityMonitoringEnabled:YES];  // enable screen dimming

remember input value:

static BOOL idleTimerDisabled;
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
- (void)applicationDidFinishLaunching:(UIApplication *)application
 { idleTimerDisabled =
 [[UIApplication sharedApplication] isIdleTimerDisabled]; ...}

turn off the proximity sensor and set input autolocking setting on application exit (including home-button exit):

- (void)applicationWillTerminate:(UIApplication *)application{ [[UIDevice currentDevice]
setProximityMonitoringEnabled:NO]; [[UIApplication sharedApplication] setIdleTimerDisabled:
idleTimerDisabled]; // disable autolocking}

I will make a special post when this Vipassana meditation utility will be available on app store.