Shake gesture not triggering NSLog message


#1

(Location 3893 Kindle for Mac)

xCode 4.1(1004)
iOS 6.0(10A403)
OSX 10.8.2
MBP 4.1; 6gb; SSD/HDD config

I seem to be missing something obvious here. Up until the insertion of the code highlighted between long comment lines below, the program ran as expected. With the insertion of the motionBegan() method override, I can neither trigger the NSLog event in the simulator, or on the actual device.

Any help in seeing my error would be sincerely appreciated.


#import "Hypnoview.h"

@implementation Hypnoview  // name not exactly the same as that used in the text, but consistent throughout code
@synthesize circleColor;

-   (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self setBackgroundColor:[UIColor clearColor]];
        [self setCircleColor:[UIColor lightGrayColor]];
    }
    return self;
}
////////////////////////////////////////// This code should trigger an event when the shake simulator is induced, but doesn't /////////////
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
        NSLog(@"Device started shaking!");
        [self setCircleColor:[UIColor redColor]];
}
/////////////////////////////////////////// end of suspect code ////////////////////////////////////////////////////////////////////////////
- (BOOL)canBecomeFirstResponder
{
    return YES;
}

-   (void)drawRect:(CGRect)dirtyRect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGRect bounds = [self bounds];
    
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;

    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;

    CGContextSetLineWidth(ctx, 10);
    
    [[self circleColor] setStroke];

    [[UIColor lightGrayColor] setStroke];
    
    for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -=20)
    {
        CGContextAddArc(ctx, center.x, center.y, currentRadius, 0.0, M_PI * 2.0, YES);       
        CGContextStrokePath(ctx);
    }
    
    NSString *text = @"You are getting sleepy.";
    
    UIFont *font = [UIFont boldSystemFontOfSize:28];
    
    CGRect textRect;
    
    textRect.size = [text sizeWithFont:font];
    
    textRect.origin.x = center.x - textRect.size.width / 2.0;
    textRect.origin.y = center.y - textRect.size.height / 2.0;
    
    [[UIColor blackColor] setFill];
    
    CGSize offset = CGSizeMake(4, 3);
    
    CGColorRef color = [[UIColor darkGrayColor] CGColor];
    
    [text drawInRect:textRect withFont:font];
    
    CGContextStrokePath(ctx);
}

@end

#2

Do you mean that - (void)motionBegan: withEvent: is not being invoked?
Make sure that your view is the first responder.

- (void)viewDidAppear:(BOOL)animated
{
    [self becomeFirstResponder];
}

See: About Events in iOS: “Event Types and Delivery,” “Motion Events”


#3

Thanks for your reply.

Yes, I meant that - (void)motionBegan: withEvent: is not being invoked is not being triggered. NSLog statement is not being executed.

Hypnoview.m declares itself as first responder, and, according to the console output, it does successfully become the first responder.

Here’s the log output, even after “shaking” the simulator:

2012-10-06 10:06:26.304 Hypnosister[82687:c07] Hypnoview became the first responder.
2012-10-06 10:06:26.312 Hypnosister[82687:c07] Application windows are expected to have a root view controller at the end of application launch


#4

OK. Thanks again for your help.

The error was placement of becomeFirstREsponder. I believe I called the method on view before view existed.

Open to more concise explanation of my error, if you feel that I’m not describing the situation well. I would like to understand.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    Hypnoview *view = [[Hypnoview alloc] initWithFrame:[[self window] bounds]];
    
    [[self window] addSubview:view];
    
    // Originally had BOOL success = [view becomeFirstResponder] here. Didn't work
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
        [[self window] addSubview:view];
    
    // Inserting it her, after initialization (duh) caused it to work correctly.
    
    BOOL success = [view becomeFirstResponder];
    
    if (success)
    {
        NSLog(@"Hypnoview became the first responder.");
    }
    else
    {
        NSLog(@"Could not become first responder");
    }
    
    self.window.backgroundColor = [UIColor whiteColor];
    
    [self.window makeKeyAndVisible];
    return YES;
}

#5

Hi Guys

I seem to have a similar problem. I’ve tried to utilize some of the corrections from the above posts, but somehow I can’t get the View-Object become the first responder.

Here’s my Delegate from the “HypnosisterAppDelegate.m” file

[code]- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

HypnosisterView *view = [[HypnosisterView alloc] initWithFrame:[[self window] bounds]];
[[self window] addSubview:view];

BOOL success = [view becomeFirstResponder];

if (success)
{
    NSLog(@"Hypnoview became the first responder.");
}
else
{
    NSLog(@"Could not become first responder");
}

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];
return YES;

}
[/code]

Here’s my View-File called HypnosisterView.m

[code]//
// HypnosisterView.m
// Hypnosister
//
// Created by Serge Zehnder on 11.04.13.
// Copyright © 2013 Serge Zehnder. All rights reserved.
//

#import “HypnosisterView.h”

@implementation HypnosisterView
@synthesize circleColor;

  • (void)viewDidAppear:(BOOL)animated
    {
    [self becomeFirstResponder];
    }

  • (id)initWithFrame:(CGRect)frame
    {
    self = [super initWithFrame:frame];
    if (self) {
    // All HypnosisViews start with a clear background color
    [self setBackgroundColor:[UIColor clearColor]];

      [self setCircleColor:[UIColor lightGrayColor]];
    

    }
    return self;
    }

//detect shake and if shake occured change color to red

  • (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
    if (motion == UIEventSubtypeMotionShake)
    {
    NSLog(@“Device started shaking!”);
    [self setCircleColor:[UIColor redColor]];
    }
    }

  • (void)setCircleColor:(UIColor *)clr;
    {
    circleColor = clr;
    [self setNeedsDisplay];
    }

  • (void)drawRect:(CGRect)dirtyRect
    {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextStrokePath(ctx);
    CGRect bounds = [self bounds];

    // Figure out the center of the bounds rectangle
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;

    // The radius of the circle should be nearly as big as the view
    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;

    // The thickness of the line should be 10 points wide
    CGContextSetLineWidth(ctx, 10);

    // The color of the line should be gray (red/green/blue = 0.6, alpha = 1.0);
    [[self circleColor] setStroke];

    // Draw concentric circles from the outside in
    for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20)
    {
    // Add a path to the context
    CGContextAddArc(ctx, center.x, center.y,
    currentRadius, 0.0, M_PI * 2.0, YES);

      // Perform a drawing instruction; draw current shape with current state
      CGContextStrokePath(ctx);
    

    }

    // Create a string
    NSString *text = @“You are getting sleepy.”;

    // Get a font to draw it in
    UIFont *font = [UIFont boldSystemFontOfSize:28];
    CGRect textRect;

    // How big is this string when drawn in this font?
    textRect.size = [text sizeWithFont:font];

    // Let’s put that string in the center of the view
    textRect.origin.x = center.x - textRect.size.width / 2.0;
    textRect.origin.y = center.y - textRect.size.height / 2.0;

    // Set the fill color of the current context to black
    [[UIColor blackColor] setFill];

    // The shadow will move 4 points to the right and 3 points down from the text
    CGSize offset = CGSizeMake(4, 3);

    // The shadow will be dark gray in color

    CGColorRef color = [[UIColor darkGrayColor] CGColor];

    // Set the shadow of the context with these parameters,
    // all subsequent drawing will be shadowed
    CGContextSetShadowWithColor(ctx, offset, 2.0, color);

    // Draw the string
    [text drawInRect:textRect
    withFont:font];

}

@end
[/code]

And this is my console output ->
2013-04-12 14:46:55.603 Hypnosister[30960:c07] Could not become first responder
2013-04-12 14:46:55.608 Hypnosister[30960:c07] Application windows are expected to have a root view controller at the end of application launch

Something’s off.


#6

@SergeZ

I don’t have

- (void)viewDidAppear:(BOOL)animated { [self becomeFirstResponder]; }
implemented in HypnosisterView. I’m wondering if this is causing an issue. In the documentation for becomeFirstResponder, the discussion lists

I’m assuming that since you told hypnosister to become the first responder it won’t allow another to become first responder unless told to no longer be a first responder.