New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added Extension for UIDevice #102 #104
added Extension for UIDevice #102 #104
Conversation
Yeah. I understand that. Have you seen my thought over in the #102 ? Maybe the best idea is to move all those method in a separate Class |
As mentioned in the #102 I moved these methods to a Context class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you squash all commits into one?
}() | ||
|
||
// Returns the screen size in pixels | ||
static let physicalScreenSize: String = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather like to name it nativeScreenSize to match it with the nativeBounds
. For physicalScreenSize I would expect it to be in centimeters or inch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Changed it.
@brototyp Fyi Github now has this feature to let you squash all commits with the UI. So usually it's not needed to ask contributors to squash. Learn more here: https://github.com/blog/2141-squash-your-commits |
Yeah, right. Forgot that. I rarely use GitHub. |
83c18bb
to
4b54950
Compare
@@ -0,0 +1,115 @@ | |||
import UIKit | |||
|
|||
public class Context { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imho, having nested classes with only static members (all internally available) does not add any value.
We are using namespace to avoid clashes and Device
and Application
does not share any fileprivate
code not visible to the outside.
I would just make a stand-alone Device
struct (prefer struct over class, or make class final
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we make two structs 'Device' and 'Application' not nested in a 'Context'?! What do you think @brototyp ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only value nesting both into a "Context" is for the developer. This way we declare both as being some Kind of Context and grouping both together. I am fine with both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I would go with the stand-alone Device
struct.
public class Device { | ||
|
||
/// The platform name of the device i.e. "iPhone1,1" or "iPad3,6" | ||
static let platform: String = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using static methods make access to members more easy without passing around an instance.
However it is a bit like having singletons and might bite back if you ever need to mock the class in a unit test.
But I do not think that will be an issue here, so I would keep as is and refactor later the need arise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. So refactoring wise we should add something like a current
singleton which then returns an Object with all the current values. This way we cloud instantiate a Device with mocked values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will make a proposal for the variant with the singleton.
// TODO: implement me | ||
} | ||
|
||
public class Device { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make this a struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding access control information (internal) to the top level type to be consistent with the other PR.
I think this code style guide is pretty good.
https://github.com/raywenderlich/swift-style-guide
https://github.com/github/swift-style-guide
case "iPad6,4": return "iPad Pro 9.7 (Cellular)" | ||
case "iPad6,7": return "iPad Pro 12.9 (WiFi)" | ||
case "iPad6,8": return "iPad Pro 12.9 (Cellular)" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the Piwik SDK supposed to run on WatchOS and tvOS, too? Then we should add the proper device names here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea. Yes add them please.
4b54950
to
da55a53
Compare
I added a version with a |
|
||
/// A human readable version of the platform name i.e. "iPhone 6 Plus" or "iPad Air 2 (WiFi)" | ||
/// Or the platform name in case no human readable name was found. | ||
let humanReadablePlatformName: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The human readable name could be a function that calculates the human readable version from the platform. And it could return an optional that is nil if no human readable version exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that returning an optional String is probably a good thing.
If the caller really needs a string it can do
let platformName = device.humanReadablePlatformName ?? device.platform
But that is the callers responsibility not this struct.
let osVersion: String | ||
|
||
// The screen size in points | ||
let screenSize: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the size should be a CGSize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
private static func currentNativeScreenSize() -> String { | ||
let bounds = UIScreen.main.nativeBounds | ||
return "\(bounds.size.width)x\(bounds.size.height)" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those static methods with a current
prefixed to irritate me a bit. A possible alternative would be a static method on Device
that returns a new Device populated with values for the current device. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a factory method would be great.
Even so, I think it is good practice to write small functions. The methods above does exactly what they promise :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the method names a bit to remove irritation ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that!
let screenSize: String | ||
|
||
// The screen size in pixels | ||
let nativeScreenSize: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a CGSize as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
internal struct Device { | ||
|
||
/// A shared instance holding the properties for the current device | ||
static let current:Device = Device(platform: currentPlatform(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest removing the static current
and have a factory method that returns the current device
static func makeCurrentDevice() -> Device {
let platform = currentPlatform()
...
return Device(platform: platform, ...)
}
I would only create a global shared instance later on if it becomes needed.
Most probably the "tracker class" can have a simple instance variable it can instantiate at construction by calling the static method above (reducing coupling and making testing more simple).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
fa3fbe9
to
c5d8dfc
Compare
internal struct Device { | ||
|
||
/// Creates an returns a new device object representing the current device | ||
static func makeCurrentDevice() -> Device { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not overly happy with the word make here but it's not a huge issue.
I'm not sure if the screen sizes fit in this extension, as both use the UIScreen class to get the informations.