delba / Permission

A unified API to ask for permissions on iOS
MIT License
2.9k stars 320 forks source link

Advice needed: Extend request callback with fixed action #127

Closed phlippieb closed 6 years ago

phlippieb commented 6 years ago

Use case:

Whenever a user actions on a permission request, I need to send analytics. Rather than implementing this in every callback in my code, I tried to subclass Permission and override request to do that automatically. Basically:

class PermissionWithAnalytics: Permission {
    override func request(_ callback: @escaping Permission.Callback) {
        super.request { [weak self] (status: PermissionStatus) in
            self?.recordAnalytics(status: status)

            // Call the client callback normally.
            callback(status)
        }
    }

    private func recordAnalytics(status: PermissionStatus) {
        let granted = (status == .authorized)
        switch self.type {
        case .camera: // (send analytics)
        // etc
    }
}

And then when I need to request a permission, I go

PermissionWithAnalytics.camera.request { status in
    // other callback code
}

(Note that this is a minimal example; I use many different permission types in many places, and would really prefer not to paste the same analytics code in every single callback.)

However, I'm stuck on initializing instances of Permission using my subclass type. Obviously, this part doesn't work: PermissionWithAnalytics.camera. It returns a Permission instance, not a PermissionWithAnalytics, because camera is a var on Permission. But I can't override camera since it's (1) a static var, not a class var, and (2) there are no publicly exposed initializers.

Any advice would be greatly appreciated.

komitake commented 6 years ago

@phlippieb

How about utilize Extension?

extension Permission {
    func requestWithAnalytics(_ callback: @escaping Permission.Callback) {
        request { [weak self] (status: PermissionStatus) in
            self?.recordAnalytics(status: status)

            // Call the client callback normally.
            callback(status)
        }
    }

    private func recordAnalytics(status: PermissionStatus) {
        let granted = (status == .authorized)
        switch self.type {
        case .camera: // (send analytics)
            // etc
        }
    }
}
Permission.camera.requestWithAnalytics { status in
    // other callback code
}
phlippieb commented 6 years ago

Of course! Brilliant. Thanks :)