So I am currently working on a project that includes image recognition with CreateML, CoreML, and Vision. I am still trying datasets and improving the models with CreateML, but if I change from a model to another, I have to manually change a variable let model = example() that Xcode creates for me when I import the .mlmodel file into the project. So I wanted to do a tableView with the name of those models files so if I tap on one of them, it takes me to the "RecognitionVC", passing the name as a variable so I can instantiate the class with an enum from a rawValue(string) and then access its "model variable" which I cannot achieve.
This is what the enum would look like:
enum MLModels: String {
case example
case letters
case ab
case numbers
case asl
}
And this is what I would like to achieve:
func getModel() -> AnyClass {
switch self {
case .example:
return example()
...
}
}
var model: MLModel {
switch self {
case .example:
return example()
...
}
}
I am new to these machine learning built in frameworks, if someone could let me know what am I doing wrong or how can I achieve this I would be very grateful.I am including some screenshots. And in case you want to test anything I am including the link to apple's public models:
link
When you write example() it creates an instance of a wrapper class. This is not an MLModel. However, it does have the MLModel as a property, so you could write return example().model to do what you want.
Related
I am trying to construct a UI element locator strategy for our XCUITests in swift and having troubles with my code snippet. This strategy will be used in all the page classes and will reduce lots of repetitive code in our UI tests.
We are trying to implement a page object model in our tests so we can have a clear implementation of Page structure and the corresponding actions on the page. We have two different apps with the same functionality but the element ID might change on some pages.
e.g, App A's login button's id will be aLoginButton and App B's id will be bLogin button.
I have thought about an implementation which is showed below but having few issues with it.
Raw value for enum case must be a literal. I understand enums return value should be string or an integer literal and that raises my question number 2.
Am I doing it right ? Is there a better way to do this ?
In the code below, LocatorStrategy will be on it's own file and will serve in the individual page extensions to hold/return UI element location values
P.S I am new to Swift.
class BasePage {
func qcom_rcom(qcomId: String , rcomId: String) -> String {
if QCOM
return qcomId
else
return rcomId
}
}
class LoginPage : BasePage {
override init() {
super.init()
print(Locators.menuItemName.identifier)
}
}
extension LoginPage {
enum Locators: String, LocatorStrategy {
case menuItemName = qcom_rcom("aLoginButton", "bLoginButton") // getting error here
}
}
public protocol LocatorStrategy {
var identifier: String { get }
}
public extension LocatorStrategy where Self: RawRepresentable, Self.RawValue == String {
var identifier: String {
return rawValue
}
}
LoginPage.init()
Expected : The enum class case needs to hold two sets of data for the element on a need basis if the UIelement id is different on two different apps. I don't want to create two separate case items aMenuItemName and bMenuItemName to resolve this issue.
One way to do this is to use preprocessor directives.
For example,
enum Locators: String, LocatorStrategy {
#if QCOM
case menuItemName = "aLoginButton"
#elseif RCOM
case menuItemName = "bLoginButton"
#endif
}
And then you can change whether it is QCOM or RCOM in your build settings:
Ok I have a protocol called Environment
protocol Environment {
var rootURL: String {get}
}
Then two structs:
struct Production: Environment {
var rootURL = "www.api.mybackend.com/v1"
}
struct Development: Environment {
var rootURL = "www.api.mydevelopmentbackend.com/v1"
}
A settings object with a function that retrieves the environment:
class Settings {
func getEnvironment<T>() -> T where T: Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 0:
return Development() as! T
case 1:
return Production() as! T
default:
return Development() as! T
}
}
func retreiveEnvironmentFromLocalStore() -> Int {
//Realm, SQLLite, Core Date, I don't really care for this example.
//Let's just say it defaults to returning 1
}
}
I really want to keep moving in a Protocol Oriented Programming direction but now when I call this function on a settings object and try to use the rootURL property the compiler complains it can't figure out the type. So, to better my understanding and to maybe find a solution:
1) Why does it care about the type if I am accessing a property defined by a protocol that at the very least it knows the returning type conforms to?
2) Structs don't have inheritance. Should I define a base class and forget about generics?
3) Can I make my getEnvironment function better? I don't like force casting, it seems like a code smell.
4) Am I even using generics correctly here?
EDIT 1:
To be clear, I want one function that returns a struct that I know will have this property.
Am I even using generics correctly here?
No, I don't think so. You are saying that getEnvironment will return T which can be any type that the client code specifies, as long as it implements Environment. However, the implementation of the method doesn't do this. It will only return two kinds of Environments, and which type it returns is not determined by the client code. The type returned depends on what retreiveEnvironmentFromLocalStore returns. Hence, generics is not suitable in this case.
Since the type of environment it returns is decided by the implementation of the method, instead of the client code, you should make use of polymorphism here - make it return an Environment instead:
func getEnvironment() -> Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 0:
return Development()
case 1:
return Production()
default:
return Development()
}
}
I really want to keep moving in a Protocol Oriented Programming direction
I suggest instead you try to move in a clear, understandable code direction, regardless of what the trendy orientation is.
Here's your function declaration:
func getEnvironment() -> T where T: Environment
This says that getEnvironment() will return an object of some type T, where T is deduced at compile time based on the code that calls getEnvironment().
What types could T be? It could be either Production or Development. For example, you could write:
let e: Production = Settings().getEnvironment()
This lets the compiler deduce that getEnvironment() returns a Production (which is an Environment) at this call site.
But there's a problem: getEnvironment() might try to return a Development anyway, based on the random number generator inside retreiveEnvironmentFromLocalStore. Then you'll get a crash at run time when it fails to cast Development to Production.
Why do you think getEnvironment() needs to be generic at all? Based on the code in your question, it shouldn't be.
import Foundation
protocol Environment {
var rootURL: String {get}
}
struct Production: Environment {
var rootURL = "www.api.mybackend.com/v1"
}
struct Development: Environment {
var rootURL = "www.api.mydevelopmentbackend.com/v1"
}
class Settings {
func getEnvironment() -> Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 1: return Production()
default: return Development()
}
}
func retreiveEnvironmentFromLocalStore() -> Int {
return Int(arc4random())
}
}
let settings = Settings()
let e = settings.getEnvironment()
Style note: the Swift API Design Guidelines advise us to
Name functions and methods according to their side-effects
Those without side-effects should read as noun phrases, e.g. x.distance(to: y), i.successor().
Unless the methods in Settings have important side effects, better names would be environment() and rawEnvironmentFromLocalStore().
The Swift developers seem to be saying that polymorphism should be accomplished via protocols, not class inheritance. For example, let's say you have an array of Shapes and the Shapes have different draw methods, Shape should be a protocol not a superclass.
protocol Shape {
func draw()
}
class Circle: Shape {
func draw() { print("Drawing a circle") }
}
class Triangle: Shape {
func draw() { print("Drawing a triangle") }
}
var shapes = [Shape]()
func fillShapes() {
//... Add circles and triangles to shapes ...
}
// run
fillShapes()
for shape in shapes {
shape.draw()
}
Now say you want to build Shapes based on user input which produces Strings. How would you write a Shape constructor that accepts String as input, in the most Swift-y way?
Cristik in this question suggests a global function like this:
func buildShape(kind: String) -> Shape? {
switch kind {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil // Error - bad Shape
}
}
This seems messy to me. I would rather the constructor was incorporated into Shape.
So my first attempt was
extension Shape {
static func build(kind: String) -> Shape? {
switch kind {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil // Error - bad Shape
}
}
}
But calling Shape.build("Circle")! produces error: static member 'build' cannot be used on instance of type 'Shape.Protocol'
I also tried
extension Shape {
class Factory {
func build(string: String) -> Shape? {
switch kind {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil
}
}
}
static let factory = Factory()
}
shapes.append(Shape.factory.build("Circle")!)
But it says Factory cannot be defined inside a protocol extension.
How does Swift want us to make flexible constructors?
You are overthinking the problem. There is nothing cleaner than a "global" function.
The problem with global functions in some languages is that they are polluting the global namespace which leads to name conflicts.
However, every Swift project has its own namespace and every framework it imports has also its own namespace, so there is no problem with name conflicts, thus, there is nothing wrong with global functions.
There is no need to wrap simple functions into Factory classes just to create an illusion of a namespace (this would be the correct solution in Java because you cannot create a global function in Java).
Function accessed as Shape.Factory.build(...) is not any better than a function accessed using buildShape(...).
If you really want to have a namespace, you can just wrap your functions into a struct:
struct Shapes {
static func buildShape(kind: String) -> Shape? {
switch kind {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil // Error - bad Shape
}
}
}
and call it as Shapes.buildShape(...) but there is not real need for it.
The protocol cannot (and in my personal opinion, should not) be used as a "factory".
A protocol is a set of rules that a construct follows, not a concrete construct itself. A factory should be a concrete type, not a "set of rules". The solution is to have a separate ShapeFactory construct (be it a class, struct or enum), with static/non-static build functions.
As for the "messy" part; I agree. It is kind of messy. Swift doesn't isn't capable of things like struct Shape.Factory { }. There's no real way to get around it without making a compromise / rewriting the compiler, the latter of which can actually be achieved with some good constructive criticism at the swift-evolution mailing list.
I wouldn't do for a Factory method on Shape, neither a protocol nor a super class should know details about implementations or derived classes. I'd rather go for a ShapeBuilding protocol and a factory class.
protocol Shape {
func draw()
}
protocol ShapeBuilding {
static func build(kind:String) -> Shape?
}
struct ShapeBuilder: ShapeBuilding {
static func build(kind: String) -> Shape? {
switch kind {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil // Error - bad Shape
}
}
}
let circle = ShapeBuilder.build("Circle")
Motto: Just because Swift offers extensions we don't have to force everything into extension.
All three of you have given me good insight into this question. I now see that it is a much deeper question than I first imagined.
Here is my consolidated answer.
The Swift message is Avoid Building Abstract Class Hierarchy. Protocols are glue (or grease maybe?) not abstract superclasses.
In Swift, a protocol like Shape is not an abstract superclass of Circle and Triangle in the Java sense. Don't try to put factory constructors (constructors that can return more than one type) into protocols.
The previous version of this post suggested that shapes could hold the differentiated construction code. But I have changed my mind. shapes shouldn't know about circles and triangles either. shapes is polymorphic and that's what polymorphic means. Therefore I have substantially changed this post. If there was strike-through I would use it but I don't see it.
I now think a global function like this is the right way.
func buildShapeFrom(userInput: String) -> Shape? {
switch userInput {
case "Circle": return Circle()
case "Triangle": return Triangle()
default: return nil // Error - bad input
}
}
If there's an appropriate structure on the user input side, perhaps it could go there. The user cares whether it is a circle or a triangle, but Shape shouldn't and neither should shapes.
Comments welcome.
I cannot find documentation on the Parse.com table column Object data type. I assume it is an object in the context of software development. However, what is the syntax to use to enter an object into the object column? I would be interested to know both the programmatic steps to take (not too concerned about which language, more concerned about actions to take to save to the object column), but I would be even more interested to know how to enter an object into the table from the Parse.com website. Can we do this from the Data section of the "Core" tab, in the Parse.com Dev webpage for the app?
I did this little test in Swift to try and save an object with a property of type object (myCar) to the table from code (I have a Parse.com table with class name Test, which has an object column called myCar). It is causing an error (I'm new to iOS so cannot find out much about the error):
Car class
class Car {
var doors = 4
func addDoor() {
doors++
}
}
client code:
override func viewDidLoad() {
var testMan = PFObject(className:"Test")
var car = Car()
testMan["myCar"] = car //////////////// error here
testMan.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
println("Success")
} else {
// There was a problem, check error.description
println("Failure")
}
}
}
well, u're mixing swift objects with parse objects .. if you want a Car object linked to your Test class you must create it in parse database (+ add class -> car -> and then create properties in it). When you have created parse class Car u can use it in swift code as let car = PFObjecT(className: "Car") and later on assign that class to test object with testMan["myCar"] = car
In the app that I'm currently working on, I try to take advantage of the new protocol extension feature in Swift. The idea is that I have a lot of classes implementing the same protocol. Since all these classes should have the same computed properties, and since the properties should behave identically in de different classes, I thought it would be nice to add the functionality only once.
My code is structured as the following example
protocol SomeProtocol { ... }
// There could potentially be unlimited different versions of "SomeClass" that implements "SomeProtocol"
class SomeClass : SomeProtocol { ... }
extension SomeProtocol {
var computedProperty1: Type? {
get { getData(SOME_ENUM) }
set { validateAndSave(newValue, atKey: SOME_ENUM) }
}
var computedProperty2: Type? {
get { getData(SOME_OTHER_ENUM) }
set { validateAndSave(newValue, atKey: SOME_OTEHR_ENUM) }
}
...
func getData(atKey: ENUM_TYPE) -> Type? {
[NEED SOME WAY TO GET THE SAVED DATA AND RETURN IT]
}
func validateAndSave(value: Type?, atKey: ENUM_TYPE) {
[NEED SOME WAY TO SAVE DATA FOR LATER RETURNING]
}
}
// The properties needs to be visible to the client code like this:
class ClientCode {
let someClassObject: SomeProtocol = SomeClass()
someClassObject.computedProperty1 = Type()
print(someClassObject.computedProperty1)
}
(The code above shows signs of storing the data in different dictionaries, which was my first thought)
The problem is that an extension does not support stored properties. But where/how do I store the data submitted to the computed properties then?
I can think of 2 different solutions, but none of them good..
I could transform the extension into a class that implements SomeProtocol instead, and then make SomeClass a subclass of it. That would allow me to save the data in stored properties. But it would also require me to implement all the methods the protocol requires in the new class - and that makes absolutely no sense, since it's the different versions of SomeClass that should provide different functionality..
I could just drop the entire extension idea, and move all the properties into SomeProtocol. But that would require me to implement all the computed properties in all the different versions of SomeClass with identical functionality, and the whole point of my extension idea was to avoid writing the same implementation for the same properties over and over again..
Is there some completely easy logical solution that I have overlooked?
... or a nice way to save data in a protocol extension that I do not know about?
... or another way of obtaining the desired functionality?
... or should I just suck it up and use one of my not-so-pretty solutions?
Assuming I understand the question correctly to work around the fact that protocol extensions don't support stored properties you could extend NSObject and use the objective C runtime to store your properties.
import ObjectiveC
private var AssociationKey: UInt8 = 0
class YourStoredObject {
// Whatever object your are persisting
}
extension NSObject {
var yourStoredObject: (YourStoredObject)! {
get {
return objc_getAssociatedObject(self, &AssociationKey) as? YourStoredObject
}
set(newValue) {
objc_setAssociatedObject(self, &AssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
}
protocol YourProtocol {
var yourStoredObject: YourStoredObject! { get set }
}
extension YourProtocol {
func customYourStoredObjectGetter() -> YourStoredObject {
return yourStoredObject
}
}
extension UILabel : YourProtocol {
func myExtendedFunc() {
// Get (and print) your object directly
print(yourStoredObject)
// Get your object through a protocol custom getter
print(customYourStoredObjectGetter())
// Set your object
yourStoredObject = YourStoredObject()
}
}
I'm not saying this is the best solution but this is the only solution I can think of. I'm also looking for nicer Swift alternatives but still have not found any.
Protocol extension? Why?
Sometimes we get so hung up on an idea that we ignore a practical solution staring right at our face.
1. Do you have set of computed properties? No, you want stored properties.
Since all these classes should have the same computed properties, and
since the properties should behave identically in de different
classes...
... but later
The problem is that an extension does not support stored properties.
But where/how do I store the data submitted to the computed properties
then?
2. Assuming that it is a set of stored properties that you want, you practically provided the solution yourself! Made one change that will make sense now.
I could transform the extension into a class that implements
SomeProtocol instead, and then make SomeClass a subclass of it. That
would allow me to save the data in stored properties.
You extend the class whenever you want to and then confirm its subclasses to SomeProtocol to get the features. This is cleaner.
On a side note, Swift's protocols not being able to store properties is by design. Protocols do not have existence in their own right and it doesn't make sense to add stored properties in them.