Mik*_*ter 152 iphone objective-c ios idle-timer
是否有人实施了一项功能,如果用户在一段时间内没有触摸屏幕,您会采取某种行动吗?我正试图找出最好的方法.
UIApplication中有一些与此有关的方法:
[UIApplication sharedApplication].idleTimerDisabled;
Run Code Online (Sandbox Code Playgroud)
如果你反而有这样的事情会很好:
NSTimeInterval timeElapsed = [UIApplication sharedApplication].idleTimeElapsed;
Run Code Online (Sandbox Code Playgroud)
然后我可以设置一个计时器并定期检查该值,并在超过阈值时采取一些措施.
希望这能解释我在寻找什么.有没有人已经解决过这个问题,或者对你将如何做到这一点有任何想法?谢谢.
Mik*_*ter 152
这是我一直在寻找的答案:
让您的应用程序委托子类UIApplication.在实现文件中,覆盖sendEvent:方法,如下所示:
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
// Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
NSSet *allTouches = [event allTouches];
if ([allTouches count] > 0) {
// allTouches count only ever seems to be 1, so anyObject works here.
UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
[self resetIdleTimer];
}
}
- (void)resetIdleTimer {
if (idleTimer) {
[idleTimer invalidate];
[idleTimer release];
}
idleTimer = [[NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO] retain];
}
- (void)idleTimerExceeded {
NSLog(@"idle time exceeded");
}
Run Code Online (Sandbox Code Playgroud)
其中maxIdleTime和idleTimer是实例变量.
为了使其工作,您还需要修改main.m以告诉UIApplicationMain使用您的委托类(在此示例中为AppDelegate)作为主要类:
int retVal = UIApplicationMain(argc, argv, @"AppDelegate", @"AppDelegate");
Run Code Online (Sandbox Code Playgroud)
Chr*_*les 86
我有一个空闲计时器解决方案的变体,它不需要子类化UIApplication.它适用于特定的UIViewController子类,因此如果您只有一个视图控制器(如交互式应用程序或游戏可能有)或只想在特定视图控制器中处理空闲超时,则非常有用.
每次重置空闲计时器时,它也不会重新创建NSTimer对象.如果计时器触发,它只会创建一个新的.
您的代码可以调用resetIdleTimer可能需要使空闲计时器无效的任何其他事件(例如重要的加速度计输入).
@interface MainViewController : UIViewController
{
NSTimer *idleTimer;
}
@end
#define kMaxIdleTimeSeconds 60.0
@implementation MainViewController
#pragma mark -
#pragma mark Handling idle timeout
- (void)resetIdleTimer {
if (!idleTimer) {
idleTimer = [[NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds
target:self
selector:@selector(idleTimerExceeded)
userInfo:nil
repeats:NO] retain];
}
else {
if (fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) {
[idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]];
}
}
}
- (void)idleTimerExceeded {
[idleTimer release]; idleTimer = nil;
[self startScreenSaverOrSomethingInteresting];
[self resetIdleTimer];
}
- (UIResponder *)nextResponder {
[self resetIdleTimer];
return [super nextResponder];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self resetIdleTimer];
}
@end
Run Code Online (Sandbox Code Playgroud)
(为简洁起见,不包括内存清理代码.)
Ser*_*nik 20
对于swift v 3.1
别忘了在AppDelegate // @ UIApplicationMain中注释这一行
extension NSNotification.Name {
public static let TimeOutUserInteraction: NSNotification.Name = NSNotification.Name(rawValue: "TimeOutUserInteraction")
}
class InterractionUIApplication: UIApplication {
static let ApplicationDidTimoutNotification = "AppTimout"
// The timeout in seconds for when to fire the idle timer.
let timeoutInSeconds: TimeInterval = 15 * 60
var idleTimer: Timer?
// Listen for any touch. If the screen receives a touch, the timer is reset.
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
if idleTimer != nil {
self.resetIdleTimer()
}
if let touches = event.allTouches {
for touch in touches {
if touch.phase == UITouchPhase.began {
self.resetIdleTimer()
}
}
}
}
// Resent the timer because there was user interaction.
func resetIdleTimer() {
if let idleTimer = idleTimer {
idleTimer.invalidate()
}
idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds, target: self, selector: #selector(self.idleTimerExceeded), userInfo: nil, repeats: false)
}
// If the timer reaches the limit as defined in timeoutInSeconds, post this notification.
func idleTimerExceeded() {
NotificationCenter.default.post(name:Notification.Name.TimeOutUserInteraction, object: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
创建main.swif文件并添加它(名称很重要)
CommandLine.unsafeArgv.withMemoryRebound(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc)) {argv in
_ = UIApplicationMain(CommandLine.argc, argv, NSStringFromClass(InterractionUIApplication.self), NSStringFromClass(AppDelegate.self))
}
Run Code Online (Sandbox Code Playgroud)
观察任何其他类的通知
NotificationCenter.default.addObserver(self, selector: #selector(someFuncitonName), name: Notification.Name.TimeOutUserInteraction, object: nil)
Run Code Online (Sandbox Code Playgroud)
Bri*_*ing 12
这个线程是一个很好的帮助,我把它包装成一个发送通知的UIWindow子类.我选择通知使它成为一个真正的松耦合,但你可以很容易地添加一个委托.
这是要点:
此外,UIApplication子类问题的原因是NIB被设置为创建2个UIApplication对象,因为它包含应用程序和委托.UIWindow子类虽然很好用.
有一种方法可以在整个应用程序范围内执行此操作,而无需单个控制器执行任何操作。只需添加一个不会取消触摸的手势识别器即可。这样,计时器将跟踪所有触摸,并且其他触摸和手势根本不受影响,因此其他人不必知道这一点。
fileprivate var timer ... //timer logic here
@objc public class CatchAllGesture : UIGestureRecognizer {
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
}
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
//reset your timer here
state = .failed
super.touchesEnded(touches, with: event)
}
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
}
}
@objc extension YOURAPPAppDelegate {
func addGesture () {
let aGesture = CatchAllGesture(target: nil, action: nil)
aGesture.cancelsTouchesInView = false
self.window.addGestureRecognizer(aGesture)
}
}
Run Code Online (Sandbox Code Playgroud)
在您的应用程序委托的 did finish launch 方法中,只需调用 addGesture 即可完成设置。所有触摸都将通过 CatchAllGesture 的方法,而不会妨碍其他功能。
小智 5
实际上,子类化的想法很有效。只是不要让您的委托成为UIApplication子类。创建另一个继承自的文件UIApplication(例如 myApp)。在 IB 中将fileOwner对象的类设置为myApp并在 myApp.m 中实现上述sendEvent方法。在 main.m 中:
int retVal = UIApplicationMain(argc,argv,@"myApp.m",@"myApp.m")
Run Code Online (Sandbox Code Playgroud)
等等!
| 归档时间: |
|
| 查看次数: |
66252 次 |
| 最近记录: |