13

当我尝试使用 (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event 来捕获抖动事件时,我遇到了一些问题。问题是该函数甚至没有运行,即使我覆盖 canBecomeFirstResponder 并将其设置为返回 YES。我看过其他人的帖子有这个问题,但我还没有找到答案。

谢谢你的帮助!

第一个示例 .h(从 UIView 继承的类 - 从应用委托类“调用”){

@class TestApplicationView;

@interface TestApplicationView : UIView {

    IBOutlet UIView *view;
}

}

第一个例子 .m {

- (id)initWithCoder:(NSCoder *)coder
{
    [self setUpView];
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    [self setUpView];
    return self;
}

- (void)setUpView
{
    [self becomeFirstResponder];
    NSLog(@"First Responder - %d", [self isFirstResponder]);
}

}

第二个示例 .h(继承自 UIApplicationDelegate 和 UIScrollViewDelegate 的类){

#import <UIKit/UIKit.h>

@class TestApplicationViewController;

@interface TestApplicationAppDelegate : NSObject <UIApplicationDelegate, UIScrollViewDelegate> {

IBOutlet UIWindow *window;
IBOutlet UIScrollView *scrollView;
}

}

第二个例子 .m {

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    [self becomeFirstResponder];
}

}

-- 第二个示例返回以下警告:“TestApplicationAppDelegate”可能无法响应“-becomeFirstResponder”

4

2 回答 2

31

我假设您想在UIViewController. 使有UIViewController能力成为第一响应者:

- (BOOL)canBecomeFirstResponder {
     return YES;
}

使UIViewController成为第一响应者viewDidAppear:

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

如果视图包含任何可能成为第一响应者的元素,例如 a UITextField,请确保该元素在某个时候退出第一响应者。UITextField例如,使用 aUIViewController将需要实现UITextFieldDelegate协议,并且实际上是委托。那么,在textFieldShouldReturn:

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
    // Hides the keyboard
    [theTextField resignFirstResponder];
    // Returns first responder status to self so that shake events register here
    [self becomeFirstResponder];
    return YES;
}

实施motionEnded:withEvent:

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if ( event.subtype == UIEventSubtypeMotionShake ) {
    // Do something
    }

    if ([super respondsToSelector:@selector(motionEnded:withEvent:)]) {
        [super motionEnded:motion withEvent:event];
    }
}

Apple 的 Matt Drance在 iPhone 开发者论坛上有一篇很好的帖子(需要注册为开发者)。

更新:在 UIView 的子类中实现

正如评论中所讨论的,这也适用于UIView. 这是构建一个最小示例的方法。

创建一个新的基于视图的应用程序项目,将其命名为ShakeTest. 创建一个新的子类UIView,调用它ShakeViewShakeView.h看起来像这样:

#import <UIKit/UIKit.h>
@interface ShakeView : UIView {
}
@end

ShakeView.m看起来像这样:

#import "ShakeView.h"
@implementation ShakeView
- (BOOL)canBecomeFirstResponder {
    return YES;
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if ( event.subtype == UIEventSubtypeMotionShake ) {
        NSLog(@"Shake!");
    }

    if ([super respondsToSelector:@selector(motionEnded:withEvent:)]) {
        [super motionEnded:motion withEvent:event];
    }
}
@end

ShakeTestViewController.h看起来像这样:

#import <UIKit/UIKit.h>
#include "ShakeView.h"
@interface ShakeTestViewController : UIViewController {
    ShakeView *s;
}
@end

ShakeTestViewController.m看起来像这样:

#import "ShakeTestViewController.h"
@implementation ShakeTestViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    s = [[ShakeView alloc] init];
    [[self view] addSubview:s];
    [s becomeFirstResponder];
}
- (void)dealloc {
    [s release];
    [super dealloc];
}
@end

构建并运行。点击 Cmd-Ctrl-Z 摇动 iPhone 模拟器。惊叹于日志消息。

于 2009-08-28T01:49:21.703 回答
0

您是否实施了旧方法

'加速度计:didAccelerate'

? 如果您实现了旧的应用程序范围方法,则需要在调用新方法之前将其删除。

于 2009-08-27T19:17:11.947 回答