Coder Social home page Coder Social logo

Comments (5)

dennisweissmann avatar dennisweissmann commented on July 4, 2024

Hi @beny, I'm totally aware of this issue. When I first wrote the code I thought about it for a very long time because, as you said, it's really annoying to branch your code everywhere depending on the target platform. The reasons why I chose this path are the following:

  • It seems that it is the direction Swift takes
  • Adding more and more devices makes it more complicated to handle all cases (what if your app is exclusively iOS but the framework wants you to handle cases for each Apple TV, each Apple Watch** and each MacBook**)
  • Currently I have to write this, because not all funcs and vars are available everywhere I'm planning to unify the API as much as possible (there are some cases which don't make sense), but this also seems to be a direction of Swift (e.g. you can add methods to Arrays only if they contain Ints). I thinks that's similar.
  • Ultimately, even if the impact on code size is negligibly small, watchOS code should not be delivered with iOS code (I think this should also be semantically separated, communicated to the developer though the use of #if os(iOS) etc.)

Or is there any issue with Simulator detection or something else?

IIRC there are plans to add an #if arch(simulator) or similar and I thought about whether or not we should move to this as well... On the one hand side I think it would clean-up the code (strictly, you don't have a .simulator case on iOS [which feels right because there is no real Simulator device], but on the other hand it complicates code on the consumer side of the framework a lot ...

That being said, I'm not sold on the current design and I'd very much appreciate discussing a different solution :) Thanks for starting this!

[Since we're still on 0.x.x releases the API can change dramatically (though I would like it to not change too much ...). I'm currently working on a protocol-oriented implementation that provides the exact same API.]

** Those are features I'm planning to provide eventually, currently there's only iDevices and Apple TV's.

from devicekit.

dennisweissmann avatar dennisweissmann commented on July 4, 2024

Hi @beny (and everyone who thankfully watches this project or might read this by accident),

Taking your thoughts (hopefully) I tried to come up with something (this is just bikeshedding at the moment, but I hope you get the idea):

The idea is that we use a DeviceType protocol to collect all the common functionality. Then, there is no Device type anymore but a Phone, Pad, Watch, TV, Computer type. All of those are available on all platforms, having a failable initializer they could only be instantiated on their corresponding Device (so on an iPhone you cannot create a Pad).

Minimal implementation (requires Swift 3):

protocol DeviceType: Equatable {
  init?()
  var name: String { get }
}

enum Phone: DeviceType {

  case iPhone1
  case iPhone2

  var name: String { return "Phone" }

  init?() {
    self = .iPhone1
  }

}

enum Pad: DeviceType {

  case iPad1
  case iPad2

  var name: String { return "Pad" }

  init?() {
    self = .iPad1
  }

}

func == (lhs: DeviceType, rhs: DeviceType) -> Bool {
  return lhs.name == rhs.name
}

// Would be defined inside the framework
let currentDevice: DeviceType = Phone() ?? Pad()!   // Where can we put `currentDevice`?, don't like it global...

Now, the interesting part. This is how the call site would look like:

func test() {
  let name = currentDevice.name

  if currentDevice is Pad {
  }

  if let pad = currentDevice as? Pad {
    if pad == .iPad1 {
    }
  }

}

What I really like about this approach is that we can use the is language construct to check whether or not we are currently on that device (instead of the current .is***** methods). Depending on how much functionality we put into the DeviceType protocol the as? casting would be mostly unnecessary.

What do you all think? Any feedback is very welcome!

from devicekit.

beny avatar beny commented on July 4, 2024

It looks great, easy to read the code with the is and that's good thing. The latter example would be probably also (don't know if it's valid syntax in Swift 3):

if let pad = currentDevice as? Pad where pad == .iPad1 {}

Looking forward to this update.

from devicekit.

dennisweissmann avatar dennisweissmann commented on July 4, 2024

Hey @beny! Sorry it took me so long, I have a branch for you (and others of course) to play with: https://github.com/dennisweissmann/DeviceKit/tree/WIP/the-great-protocol-transformation

However, this is a work in progress and only rudimentary features are implemented, namely: Device detection, device group detection.

There is definitely a need for a few helper methods to make detection easier and don't require the consumer of the API to write the code I have put in the "Tests" (it's not really tested atm :D)

Currently you can identify your device like this:

  func testCurrentDevice() {
    let currentDevice = DeviceKit.currentDevice
    switch currentDevice {
    case let currentDevice as Pad:
      switch currentDevice {
      case .iPad2: print("Is iPad 2")
      case .iPad3: print("Is iPad 3")
      case .iPad4: print("Is iPad 4")
      case .iPadAir: print("Is iPad Air")
      case .iPadAir2: print("Is iPad Air 2")
      case .iPadMini: print("Is iPad Mini")
      case .iPadMini2: print("Is iPad Mini 2")
      case .iPadMini3: print("Is iPad Mini 3")
      case .iPadMini4: print("Is iPad Mini 4")
      case .iPadPro: print("Is iPad Pro")
      case .simulator(let pad): print("Is iPad simulator: \(pad)")
      case .unknownPad(let unknown): print("Currenlty unknown device: \(unknown)")
      }
    case is Phone: print("Is iPhone")
    default: break
    }
    // Or a short way:
    print("\(currentDevice)")
  }

Currently only iPads, iPhones, and Apple TV are supported, but this will (hopefully) change in the future.

If you have time I would love to hear from you what you think :)

from devicekit.

dennisweissmann avatar dennisweissmann commented on July 4, 2024

I’ll close this issue since there doesn’t seem to be very much interest in that feature, thanks for proposing it anyways! 🙏

from devicekit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.