Detecting device shake using iOS 8 and Swift

To respond to a shake gesture in iOS 8 using Swift, you must override three methods in the ViewController that will respond to the shake: viewDidAppear(animated: Bool), canBecomeFirstResponder() -> Bool and motionEnded(motion: UIEventSubtype, withEvent event: UIEvent!)


    override func preferredStatusBarStyle() -> UIStatusBarStyle {
        return .LightContent
    }
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.becomeFirstResponder()
    }
    
    override func canBecomeFirstResponder() -> Bool {
        return true
    }
    
    override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent!) {
        if(event.subtype == UIEventSubtype.MotionShake) {
            var alert = UIAlertController(title: "Shaken",
                message: "Not Stirred",
                preferredStyle: UIAlertControllerStyle.Alert)
            alert.addAction(UIAlertAction(title: "OK",
                style: UIAlertActionStyle.Default, handler: nil))
            self.presentViewController(alert, animated: true, completion: nil)
        }
    }

Creating a Singleton in Swift – The Nested Struct Approach


class AppService : BaseService {
    class var sharedInstance : AppService {
        struct Static {
            static let instance : AppService = AppService()
        }
        return Static.instance
    }
}

While refactoring one of my apps recently, I had to figure out how to create a singleton in Swift. This approach seems like the most widely accepted way. The shared instance is a class variable. A closure is used to initialize and return a static instance that is contained in the nested Static struct within the closure. Oodles of joy. This is called the nested struct approach. There are two more which can be seen here:


https://github.com/hpique/SwiftSingleton

Dragging a CALayer

Put together a quick demo showing how to drag a CALAyer by capturing touch events and applying animations to the layer based on the position of the touches. Illustrates basic core animation concepts.

https://github.com/RTimal/CALayer-Drag

//
//  RTViewController.m
//  LayerTests
//
//  Created by Rajiev Timal on 3/7/14.
//  Copyright (c) 2014 Rajiev. All rights reserved.
//

#import "RTViewController.h"

typedef NS_ENUM(NSInteger, LayerState){
    LayerStateResting,
	LayerStatePickedUp,
};

@interface RTViewController ()

@property (nonatomic , strong) CALayer *topLayer;
@property (nonatomic , strong) CALayer *topLayer2;
@property (nonatomic, assign) LayerState currentLayerState;
@property (nonatomic, assign) CGPoint oldPoint;

@end

@implementation RTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	self.topLayer = [CALayer layer];
	UIImage *appleImage = [UIImage imageNamed:@"applications-internet_full.png"];
	self.topLayer.contents = (__bridge id)([appleImage CGImage]);
	CATransform3D perspectiveTransform = CATransform3DIdentity;
	perspectiveTransform.m34 = -1/500.f;
	self.view.layer.sublayerTransform = perspectiveTransform;
	self.topLayer.position = CGPointMake(130.f,250.f);
	self.topLayer.bounds = CGRectMake(0.f, 0.f, 200.f,200.f);
	[self.view.layer insertSublayer:self.topLayer above:self.view.layer];


	self.topLayer2 = [CALayer layer];
	UIImage *appleImage2 = [UIImage imageNamed:@"applications-internet_full.png"];
	self.topLayer2.contents = (__bridge id)([appleImage CGImage]);
	CATransform3D perspectiveTransform2 = CATransform3DIdentity;
	perspectiveTransform2.m34 = -1/500.f;
	self.view.layer.sublayerTransform = perspectiveTransform2;
	self.topLayer2.position = CGPointMake(130.f,250.f);
	self.topLayer2.bounds = CGRectMake(0.f, 0.f, 200.f,200.f);
	[self.view.layer insertSublayer:self.topLayer2 above:self.view.layer];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
	[super touchesBegan:touches withEvent:event];
	CGPoint location = [[touches anyObject] locationInView:self.view];
	self.oldPoint = location;

	if(CGRectContainsPoint(self.topLayer.frame, location))
	{
		self.currentLayerState = LayerStatePickedUp;
		[CATransaction begin];
		[CATransaction setAnimationDuration:.5f];
		self.topLayer.zPosition = 40.f;
		self.topLayer.transform = CATransform3DRotate(self.topLayer.transform, .1, 0.f, 1.f,0.f);
		[CATransaction setCompletionBlock:^{
			self.topLayer.zPosition = 40.f;
			self.topLayer.transform = CATransform3DRotate(self.topLayer.transform, .1, 0.f, 1.f,0.f);
		}];

		[CATransaction commit];

		CABasicAnimation *spinningAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
		[spinningAnimation setFromValue:@0];
		[spinningAnimation setToValue:@30];

		CABasicAnimation *spinningAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
		[spinningAnimation2 setFromValue:@0];
		[spinningAnimation2 setToValue:@30];

		CABasicAnimation *spinningAnimation3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
		[spinningAnimation2 setFromValue:@0];
		[spinningAnimation2 setToValue:@30];

		CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
		[animationGroup setAnimations:@[spinningAnimation,spinningAnimation2, spinningAnimation3]];
		animationGroup.duration = 5.f;
		animationGroup.repeatCount = 1000000;
		[self.topLayer addAnimation:animationGroup forKey:@"spinXandYZ"];
	}
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	[super touchesEnded:touches withEvent:event];
	if(self.currentLayerState == LayerStatePickedUp)
	{
		[CATransaction begin];
		[CATransaction setAnimationDuration:.5f];
		self.topLayer.zPosition = -40.f;
		[CATransaction setCompletionBlock:^{
			self.topLayer.zPosition = -40.f;
			self.topLayer.transform = CATransform3DIdentity;
		}];
		[CATransaction commit];
	}
	self.currentLayerState = LayerStateResting;
	[self.topLayer removeAllAnimations];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
	[super touchesEnded:touches withEvent:event];
	CGPoint location = [[touches anyObject] locationInView:self.view];
	if((self.currentLayerState == LayerStatePickedUp) && CGRectContainsPoint(self.topLayer.frame, location))
	{
		[CATransaction begin];
		[CATransaction setAnimationDuration:0.f];
		self.topLayer.position =  CGPointMake(self.topLayer.position.x + (location.x - self.oldPoint.x), self.topLayer.position.y + (location.y - self.oldPoint.y));
		[CATransaction commit];
		self.oldPoint = location;
	}
}

@end

Open Sourced Memorize This! iPad Game

A simple iOS memory game

https://github.com/RTimal/Memory-Tiles.git

The game can be downloaded from iTunes store here:

https://itunes.apple.com/us/app/memorize-this!/id622344158?mt=8

I’ve decided to work on some other projects including a 3d game engine, and have temporarily stopped working on this memory game. Planned updates included adding content packs with pictures/sounds on the tiles for children to use and memorize.

Memory Tiles – iPad app

Simple high score iOS memory game for iPad – a sequence of tiles are played and the user has to repeat them for points.  It’s meant to improve short term memory and visuospatial memory. Not sure what to do with it so made it open source!  There are 6 levels, each level has 10 sequences and as the sequence number goes up the sequences get longer. You could find yourself memorizing up to 54 tiles in a row in the last level. The colors are randomly generated and scores are saved across instances of the application using NSUserDefaults. I think it could actually have some implications in memory enhancement and Alzheimer’s. If anyone wants to pursue that, please feel free.

Technologies: iOS 6, Xcode, PaintCode, core graphics, core animation, UIKit, FXLabel(https://github.com/nicklockwood/FXLabel)

https://github.com/RTimal/Memory-Tiles

photo