iosswiftgrand-central-dispatchuipasteboard

Trying to wipe out pasteboard after time interval


I am trying to clear the pasteboard after a string is copied after 10s. The requirements are the following:

  1. After 10s, the copied text is cleared and therefore not pasteable in the current app and other apps as well(ex. iMessage, Safari)
  2. If non-identical text is copied, when the 10s is up the timer will not wipe it out

Attempts

  1. I have tried doing this with only DispatchQueue.main.async however, this was freezing the original app.
  2. I have tried doing it with only DispatchQueue.global(qos: .background).async however, when I switched to another app(iMessage), after 10s I could still paste the number. I had to go back to the original app and back to iMessage for it to be wiped out
  3. This is my latest attempt and its the same behavior as #2, only getting wiped out when I go back to the original app and back to iMessage
    private func clearTextAfterDelay(_ copiedCardNumber: String) {
        expirationTimer?.invalidate()
        expirationTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { timer in
            DispatchQueue.main.async {
                let currentTextOnClipBoard = UIPasteboard.general.string
                if currentTextOnClipBoard == copiedCardNumber {
                    UIPasteboard.general.setValue("", forPasteboardType: UIPasteboard.Name.general.rawValue)
                }
            }
        }

        DispatchQueue.global(qos: .background).async {
            let runLoop = RunLoop.current
            runLoop.add(self.expirationTimer!, forMode: .default)
            runLoop.run()
        }
    }

Solution

  • Along with this article and the above comment I was able to figure it out https://medium.com/@abhimuralidharan/finite-length-tasks-in-background-ios-swift-60f2db4fa01b. Cheers

    class ViewController: MvpViewController {
    
        private var expirationTimerforBackground: Timer?
        private var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid
    
        private func clearTextAfterDelay(_ copiedCardNumber: String) {
            backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
                self?.endBackgroundTask()
            }
    
            assert(backgroundTask != UIBackgroundTaskIdentifier.invalid)
    
            self.expirationTimerforBackground?.invalidate()
            self.expirationTimerforBackground = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { [weak self] _ in
                let currentTextOnClipBoard = UIPasteboard.general.string
                if currentTextOnClipBoard == copiedCardNumber {
                    UIPasteboard.general.setValue("", forPasteboardType: UIPasteboard.Name.general.rawValue)
                }
                self?.endBackgroundTask()
            }
        }
    
        private func endBackgroundTask() {
            UIApplication.shared.endBackgroundTask(backgroundTask)
            backgroundTask = UIBackgroundTaskIdentifier.invalid
        }
    }