iPhone: การตรวจจับการไม่ใช้งาน / เวลาว่างของผู้ใช้ตั้งแต่การสัมผัสหน้าจอครั้งสุดท้าย


152

มีใครบ้างที่ใช้งานฟีเจอร์นี้หากผู้ใช้ไม่ได้สัมผัสหน้าจอเป็นระยะเวลาหนึ่งคุณจะต้องดำเนินการบางอย่างหรือไม่? ฉันพยายามหาวิธีที่ดีที่สุดในการทำเช่นนั้น

มีวิธีนี้ค่อนข้างเกี่ยวข้องใน UIApplication:

[UIApplication sharedApplication].idleTimerDisabled;

มันคงจะดีถ้าคุณมีบางอย่างเช่นนี้แทน:

NSTimeInterval timeElapsed = [UIApplication sharedApplication].idleTimeElapsed;

จากนั้นฉันสามารถตั้งค่าตัวจับเวลาและตรวจสอบค่านี้เป็นระยะและดำเนินการบางอย่างเมื่อเกินขีด จำกัด

หวังว่าจะอธิบายสิ่งที่ฉันกำลังมองหา มีใครแก้ปัญหานี้แล้วหรือมีความคิดเกี่ยวกับวิธีที่คุณจะทำมันได้หรือไม่ ขอบคุณ


นี่เป็นคำถามที่ยอดเยี่ยม Windows มีแนวคิดเกี่ยวกับเหตุการณ์ OnIdle แต่ฉันคิดว่ามันเป็นเรื่องเกี่ยวกับแอพที่ไม่ได้จัดการอะไรในขณะนี้คือปั๊มข้อความกับคุณสมบัติ idleTimerDisabled ของ iOS ซึ่งดูเหมือนว่าจะเกี่ยวข้องกับการล็อคอุปกรณ์เท่านั้น ไม่มีใครรู้ว่ามีอะไรใกล้เคียงกับแนวคิด Windows ใน iOS / MacOSX หรือไม่
stonedauwg

คำตอบ:


153

นี่คือคำตอบที่ฉันค้นหา:

มีแอพพลิเคชั่นของคุณมอบให้กับคลาสย่อย 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");
}

โดยที่ maxIdleTime และ idleTimer เป็นตัวแปรอินสแตนซ์

เพื่อให้สิ่งนี้ใช้งานได้คุณต้องแก้ไข main.m ของคุณเพื่อบอก UIApplicationMain เพื่อใช้คลาสตัวแทนของคุณ (ในตัวอย่างนี้ AppDelegate) เป็นคลาสหลัก:

int retVal = UIApplicationMain(argc, argv, @"AppDelegate", @"AppDelegate");

3
สวัสดีไมค์ AppDelegate ของฉันกำลังสืบทอดจาก NSObject ดังนั้นจึงเปลี่ยนเป็น UIApplication และใช้วิธีการด้านบนเพื่อตรวจสอบว่าผู้ใช้ไม่ได้ใช้งาน แต่ฉันได้รับข้อผิดพลาด "แอปสิ้นสุดเนื่องจากข้อยกเว้นที่ไม่ถูกตรวจจับ ".. มีอะไรอีกที่ฉันต้องทำ ... ?
Mihir Mehta

7
ฉันจะเพิ่มว่าคลาสย่อย UIApplication ควรแยกออกจากคลาสย่อย UIApplicationDelegate
boliva

ฉันไม่แน่ใจว่าวิธีนี้จะทำงานกับอุปกรณ์ที่เข้าสู่สถานะไม่ใช้งานเมื่อตัวจับเวลาหยุดการยิงหรือไม่
anonmys

ทำงานไม่ถูกต้องหากฉันกำหนดให้ใช้ฟังก์ชัน popToRootViewController สำหรับเหตุการณ์หมดเวลา มันเกิดขึ้นเมื่อฉันแสดง UIAlertView จากนั้น popToRootViewController จากนั้นฉันกดปุ่มใด ๆ บน UIAlertView พร้อมตัวเลือกจาก uiviewController ซึ่งโผล่ขึ้นมาแล้ว
Gargo

4
ดีมาก! อย่างไรก็ตามวิธีการนี้จะสร้างNSTimerอินสแตนซ์จำนวนมากหากมีจำนวนมากสัมผัส
Andreas Ley

86

ฉันมีรูปแบบของโซลูชันตัวจับเวลาที่ไม่ได้ใช้งานซึ่งไม่ต้องการ UIA การแบ่งประเภทย่อย มันทำงานบนคลาสย่อย UIViewController เฉพาะดังนั้นจะมีประโยชน์ถ้าคุณมีคอนโทรลเลอร์มุมมองหนึ่งตัว (เช่นแอพแบบโต้ตอบหรือเกมอาจมี) หรือต้องการจัดการกับไทม์เอาต์ว่างในตัวควบคุมมุมมองเฉพาะ

และจะไม่สร้างวัตถุ NSTimer ใหม่ทุกครั้งที่มีการรีเซ็ตตัวจับเวลาว่าง มันจะสร้างขึ้นมาใหม่ก็ต่อเมื่อตัวจับเวลาเริ่มทำงาน

รหัสของคุณสามารถโทรresetIdleTimerหากิจกรรมอื่น ๆ ที่อาจต้องทำให้ตัวจับเวลาไม่ทำงาน (เช่นอินพุต accelerometer ที่สำคัญ)

@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

(รหัสการล้างข้อมูลหน่วยความจำไม่รวมอยู่ในช่วงเวลาสั้น ๆ )


1
ดีมาก. คำตอบนี้หิน! เอาชนะคำตอบที่ทำเครื่องหมายว่าถูกต้องแม้ว่าฉันจะรู้ว่ามันเร็วกว่านี้มาก แต่นี่เป็นทางออกที่ดีกว่าตอนนี้
Chintan Patel

นี่เป็นเรื่องดี แต่มีปัญหาหนึ่งที่ฉันพบ: การเลื่อนใน UITableViews ไม่ทำให้เกิดการเรียกกลับถัดไป ฉันยังลองติดตามผ่าน touchesBegan: และ touchesMoved: แต่ไม่มีการปรับปรุง ความคิดใด ๆ
เกร็ก Maletic

3
@GregMaletic: ฉันมีปัญหาเดียวกัน แต่ในที่สุดฉันได้เพิ่ม - (เป็นโมฆะ) scrollViewWillBeginDragging: (UIScrollView *) scrollView {NSLog (@ "จะเริ่มลาก"); } - (เป็นโมฆะ) scrollViewDidScroll: (UIScrollView *) scrollView {NSLog (@ "Did Scroll"); [ตนเองรีเซ็ต iDleTimer]; } คุณลองนี่แล้วหรือ
Akshay Aher

ขอบคุณ สิ่งนี้ยังคงมีประโยชน์ ฉันแจ้งไปยัง Swift และใช้งานได้ดี
Mark.ewd

คุณคือ rockstar รุ่งโรจน์
Pras

21

สำหรับ 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)
   }
} 

สร้างไฟล์ 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))
}

สังเกตการแจ้งเตือนในคลาสอื่น ๆ

NotificationCenter.default.addObserver(self, selector: #selector(someFuncitonName), name: Notification.Name.TimeOutUserInteraction, object: nil)

2
ผมไม่เข้าใจว่าทำไมเราต้องตรวจสอบif idleTimer != nilในsendEvent()วิธีการ?
Guangyu Wang

เราจะตั้งค่าสำหรับtimeoutInSecondsการตอบสนองจากบริการเว็บได้อย่างไร
User_1191

12

หัวข้อนี้เป็นความช่วยเหลือที่ดีและฉันห่อมันลงในคลาสย่อยของ UIWindow ที่ส่งการแจ้งเตือน ฉันเลือกการแจ้งเตือนเพื่อให้การเชื่อมต่อหลวมจริง แต่คุณสามารถเพิ่มผู้ร่วมประชุมได้ง่ายพอ

นี่คือส่วนสำคัญ:

http://gist.github.com/365998

นอกจากนี้สาเหตุของปัญหาคลาสย่อย UIApplication คือ NIB ถูกตั้งค่าให้สร้างวัตถุ UIApplication 2 รายการเนื่องจากประกอบด้วยแอปพลิเคชันและผู้รับมอบสิทธิ์ คลาสย่อย UIWindow ใช้งานได้ดี


1
คุณบอกวิธีใช้รหัสของคุณให้ฉันได้ไหม ฉันไม่เข้าใจวิธีที่จะเรียกมันว่า
R. Dewi

2
มันใช้งานได้ดีสำหรับการสัมผัส แต่ดูเหมือนจะไม่จัดการกับการป้อนข้อมูลจากแป้นพิมพ์ ซึ่งหมายความว่าจะหมดเวลาหากผู้ใช้พิมพ์ข้อมูลบนแป้นพิมพ์ gui
Martin Wickman

2
ฉันก็ไม่สามารถที่จะเข้าใจวิธีใช้ ... ฉันเพิ่มผู้สังเกตการณ์ในตัวควบคุมมุมมองของฉันและคาดว่าการแจ้งเตือนจะถูกยิงเมื่อแอพไม่มีการแตะต้อง / ไม่ได้ใช้งาน .. แต่ไม่มีอะไรเกิดขึ้น ... เช่นฉันต้องการเวลาว่าง 120 วินาทีดังนั้นหลังจาก 120 วินาที IdleNotification ควรเริ่มทำงานไม่ใช่ก่อนหน้านั้น
ตอบที่

5

จริงๆแล้วความคิดระดับรองทำงานได้ดีมาก อย่าทำให้ผู้รับมอบสิทธิ์เป็นUIApplicationคลาสย่อย สร้างไฟล์อื่นที่สืบทอดจากUIApplication(เช่น myApp) ใน IB ให้ตั้งคลาสของfileOwnerออบเจ็กต์เป็นmyAppและใน myApp.m ใช้sendEventเมธอดข้างต้น ใน main.m ทำ:

int retVal = UIApplicationMain(argc,argv,@"myApp.m",@"myApp.m")

et voilà!


1
ใช่การสร้างคลาสย่อย UIApplication แบบสแตนด์อโลนดูเหมือนว่าจะทำงานได้ดี ฉันออกจากศูนย์ที่สองในหลัก
Hot Licks

@Roby ได้ดูว่าแบบสอบถามของฉันstackoverflow.com/questions/20088521/...
Tirth

4

ฉันเพิ่งพบปัญหานี้กับเกมที่ควบคุมโดยการเคลื่อนไหวเช่นมีการล็อกหน้าจอถูกปิดใช้งาน แต่ควรเปิดใช้งานอีกครั้งเมื่ออยู่ในโหมดเมนู แทนที่จะเป็นตัวจับเวลาฉันสรุปการโทรทั้งหมดsetIdleTimerDisabledภายในชั้นเรียนขนาดเล็กที่ให้วิธีการดังต่อไปนี้:

- (void) enableIdleTimerDelayed {
    [self performSelector:@selector (enableIdleTimer) withObject:nil afterDelay:60];
}

- (void) enableIdleTimer {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}

- (void) disableIdleTimer {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}

disableIdleTimerปิดใช้งานตัวจับเวลาไม่ทำงานenableIdleTimerDelayedเมื่อเข้าสู่เมนูหรือสิ่งที่ควรทำงานด้วยตัวจับเวลาที่ไม่ทำงานและenableIdleTimerถูกเรียกจากapplicationWillResignActiveวิธีการAppDelegate ของคุณเพื่อให้แน่ใจว่าการเปลี่ยนแปลงทั้งหมดของคุณจะถูกรีเซ็ตอย่างเหมาะสมกับพฤติกรรมเริ่มต้นของระบบ
ฉันเขียนบทความและให้รหัสสำหรับการจัดการ IdleTimerManager Idle Timer Idleคลาสเดี่ยวในเกม iPhone


4

นี่เป็นอีกวิธีในการตรวจจับกิจกรรม:

มีการเพิ่มตัวจับเวลาเข้าไปUITrackingRunLoopModeดังนั้นจึงสามารถยิงได้เฉพาะเมื่อมีUITrackingกิจกรรม นอกจากนี้ยังมีข้อได้เปรียบที่ดีของการไม่สแปมสำหรับกิจกรรมการสัมผัสทั้งหมดดังนั้นจึงแจ้งว่ามีกิจกรรมในACTIVITY_DETECT_TIMER_RESOLUTIONวินาทีสุดท้าย ฉันตั้งชื่อตัวเลือกkeepAliveเนื่องจากดูเหมือนว่าเป็นกรณีการใช้งานที่เหมาะสมสำหรับสิ่งนี้ แน่นอนคุณสามารถทำสิ่งที่คุณต้องการด้วยข้อมูลที่มีกิจกรรมเมื่อเร็ว ๆ นี้

_touchesTimer = [NSTimer timerWithTimeInterval:ACTIVITY_DETECT_TIMER_RESOLUTION
                                        target:self
                                      selector:@selector(keepAlive)
                                      userInfo:nil
                                       repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:_touchesTimer forMode:UITrackingRunLoopMode];

งั้นเหรอ ฉันเชื่อว่ามันชัดเจนว่าคุณควรทำให้คุณ "keepAlive" เลือกตัวเองกับสิ่งที่คุณต้องการ บางทีฉันอาจขาดมุมมองของคุณ?
หมดเวลา Timar

คุณบอกว่านี่เป็นอีกวิธีหนึ่งในการตรวจหากิจกรรมอย่างไรก็ตามนี่เป็นการยกตัวอย่าง iVar ซึ่งเป็น NSTimer เท่านั้น ฉันไม่เห็นว่าสิ่งนี้ตอบคำถามของ OP อย่างไร
Jasper

1
ตัวจับเวลาถูกเพิ่มใน UITrackingRunLoopMode ดังนั้นจึงสามารถทำงานได้หากมีกิจกรรมของ UITracking เท่านั้น นอกจากนี้ยังมีข้อได้เปรียบที่ดีในการไม่สแปมสำหรับกิจกรรมการสัมผัสทั้งหมดดังนั้นจึงแจ้งว่ามีกิจกรรมใน ACTIVITY_DETECT_TIMER_RESOLUTION วินาทีที่ผ่านมาหรือไม่ ฉันตั้งชื่อตัวเลือก keepAlive เนื่องจากดูเหมือนว่าเป็นกรณีการใช้งานที่เหมาะสมสำหรับสิ่งนี้ แน่นอนคุณสามารถทำสิ่งที่คุณต้องการด้วยข้อมูลที่มีกิจกรรมเมื่อเร็ว ๆ นี้
หมดเวลา Timar

1
ฉันต้องการปรับปรุงคำตอบนี้ หากคุณสามารถช่วยเหลือเกี่ยวกับพอยน์เตอร์ในการทำให้ชัดเจนยิ่งขึ้นมันจะเป็นความช่วยเหลือที่ดี
หมดเวลา Timar

ฉันเพิ่มคำอธิบายของคุณลงในคำตอบของคุณ มันสมเหตุสมผลมากกว่าตอนนี้
แจสเปอร์

3

ในที่สุดคุณจำเป็นต้องกำหนดสิ่งที่คุณคิดว่าจะไม่ได้ใช้งาน - เป็นผลมาจากการที่ผู้ใช้ไม่ได้สัมผัสหน้าจอหรือสถานะของระบบหากไม่มีการใช้ทรัพยากรคอมพิวเตอร์? เป็นไปได้ในแอพพลิเคชั่นมากมายสำหรับผู้ใช้ที่จะทำบางสิ่งบางอย่างแม้ว่าจะไม่ได้มีปฏิสัมพันธ์กับอุปกรณ์ผ่านหน้าจอสัมผัส ในขณะที่ผู้ใช้อาจคุ้นเคยกับแนวคิดของอุปกรณ์ที่จะเข้าสู่โหมดสลีปและการแจ้งเตือนว่าจะเกิดขึ้นผ่านหน้าจอลดแสงไม่จำเป็นต้องเป็นกรณีที่พวกเขาจะคาดหวังบางสิ่งบางอย่างที่จะเกิดขึ้นหากพวกเขาไม่ได้ใช้งาน เกี่ยวกับสิ่งที่คุณจะทำ แต่กลับไปที่คำแถลงเดิม - ถ้าคุณพิจารณากรณีที่ 1 ให้เป็นคำจำกัดความของคุณไม่มีวิธีง่ายๆในการทำเช่นนี้ คุณจะต้องได้รับเหตุการณ์การสัมผัสแต่ละครั้ง ส่งผ่านไปยังห่วงโซ่การตอบกลับตามต้องการขณะที่สังเกตเวลาที่ได้รับ ที่จะให้พื้นฐานสำหรับการคำนวณว่าง หากคุณพิจารณากรณีที่สองเป็นคำจำกัดความของคุณคุณสามารถเล่นกับการแจ้งเตือน NSPostWhenIdle เพื่อลองและปฏิบัติตามตรรกะของคุณในเวลานั้น


1
เพื่อชี้แจงฉันกำลังพูดถึงการโต้ตอบกับหน้าจอ ฉันจะอัปเดตคำถามเพื่อสะท้อนว่า
Mike McMaster

1
จากนั้นคุณสามารถใช้บางสิ่งบางอย่างเมื่อใดก็ตามที่มีการสัมผัสเกิดขึ้นคุณอัปเดตค่าที่คุณตรวจสอบหรือแม้กระทั่งตั้งค่า (และรีเซ็ต) ตัวจับเวลาไม่ทำงานเพื่อเริ่มทำงาน แต่คุณต้องปรับใช้ตัวเอง แอพที่แตกต่างกัน
Louis Gerbarg

1
ฉันกำลังกำหนด "ว่าง" อย่างเคร่งครัดตามเวลานับตั้งแต่การสัมผัสหน้าจอครั้งล่าสุด ฉันได้รับว่าฉันจะต้องใช้มันด้วยตัวเองฉันแค่สงสัยว่าวิธีที่ "ดีที่สุด" จะเป็นอย่างไรพูดสกัดกั้นหน้าจอสัมผัสหรือถ้ามีคนรู้วิธีอื่นในการพิจารณาสิ่งนี้
Mike McMaster

3

มีวิธีที่จะทำแอพนี้ให้กว้างโดยไม่ต้องทำอะไร เพียงเพิ่มตัวรู้จำท่าทางที่ไม่ได้ยกเลิกการสัมผัส ด้วยวิธีนี้การสัมผัสทั้งหมดจะถูกติดตามสำหรับตัวจับเวลาและการสัมผัสและท่าทางอื่น ๆ จะไม่ได้รับผลกระทบดังนั้นจึงไม่มีใครรู้เรื่องนี้

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)
    }
}

ในวิธีการเปิดใช้งานเสร็จสิ้นตัวแทนของคุณเพียงแค่เรียก addGesture และคุณพร้อมแล้ว สัมผัสทั้งหมดจะต้องผ่านวิธีการของ CatchAllGesture โดยที่ไม่สามารถป้องกันการใช้งานของผู้อื่นได้


1
ฉันชอบวิธีนี้ใช้มันสำหรับปัญหาที่คล้ายกันกับ Xamarin: stackoverflow.com/a/51727021/250164
Wolfgang Schreurs

1
ใช้งานได้ดีและดูเหมือนว่าเทคนิคนี้ใช้เพื่อควบคุมการมองเห็นการควบคุม UI ใน AVPlayerViewController (การอ้างอิง API ส่วนตัว ) แอพที่เอาชนะได้-sendEvent:นั้นเกินความจำเป็นและUITrackingRunLoopModeไม่รองรับหลายกรณี
Roman B.

@RomanB ใช่ เมื่อคุณได้ทำงานกับ iOS นานพอที่คุณรู้ว่าจะมักจะใช้ "วิธีการที่เหมาะสม" และนี่คือวิธีที่ง่ายที่จะใช้ท่าทางที่กำหนดเองตามที่ตั้งใจไว้developer.apple.com/documentation/uikit/uigesturerecognizer/...
Jlam

การตั้งค่าสถานะเป็น .failed สำเร็จใน touchesEnded อย่างไร
stonedauwg

ฉันชอบวิธีการนี้ แต่เมื่อลองมันดูเหมือนว่าจะแตะก๊อกน้ำเท่านั้นไม่มีท่าทางอื่น ๆ เช่นกระทะกวาดนิ้วและสัมผัสอื่น ๆ สิ้นสุดที่ตรรกะการรีเซ็ตจะไป นั่นตั้งใจหรือไม่
stonedauwg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.