Skip to content

Allow implementations of ParseObjects to set their own className #421

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

Closed
3 tasks done
atonylai opened this issue Oct 1, 2022 · 7 comments
Closed
3 tasks done

Allow implementations of ParseObjects to set their own className #421

atonylai opened this issue Oct 1, 2022 · 7 comments
Labels
type:question Support or code-level question

Comments

@atonylai
Copy link

atonylai commented Oct 1, 2022

Current Limitation

struct extensions of ParseObject seem to force their name as the classTitle

struct GameScore: ParseObject { ... }

We use Stripe as another library - Stripe has a class called Event. One of the tables in our database that is heavily populated is already called Event.

Feature / Enhancement Description

Allow extensions of ParseObject to function more like PFObject. While it's a lot of work for us to have to add in

struct SomeDatabaseTableName: ParseObject { ... }

this is not impossible, albeit just a lot of boilerplate code.

Example Use Case

struct RandomClassName: ParseObject { 

   var className = "ActualDatabaseClassName"

 }

Alternatives / Workarounds

We could migrate the entire table into a new one and update all of the code to point to a new table, but that would still leave us at the mercy of any of our dependencies adding in a new class or struct that conflicts with ours.

3rd Party References

The original obj-c Parse SDK

@parse-github-assistant
Copy link

Thanks for opening this issue!

  • ❌ Please edit your post and use the provided template when creating a new issue. This helps everyone to understand your post better and asks for essential information to quicker review the issue.

@cbaker6 cbaker6 added the type:question Support or code-level question label Oct 1, 2022
@cbaker6
Copy link
Contributor

cbaker6 commented Oct 1, 2022

className is a computed property that has a default implementation. You can easily replace the computed property with whatever you want. Replacing default implementations is typical of Swift Protocols. See this example as well as others:

struct MyClientClassName: PareseObject {
    static var className: String {
        "MyServerClassName"
    }
}

While it's a lot of work for us to have to add in

struct SomeDatabaseTableName: ParseObject { ... }

this is not impossible, albeit just a lot of boilerplate code.

I’m not sure what you mean by “a lot of work,” but I recommend learning more about Swift Protocols (link above) as well as read about the design of this SDK in the README and it’s original evolution plan (#3 (comment)).

@atonylai
Copy link
Author

atonylai commented Oct 4, 2022

Hi, thank you for this!

a lot of work

So here's some sample code from our project

class Event {

  var PFData: PFObject!

  var available: Int
  var purchased: Int
  ... // another 20ish fields
  
  init?(with object: PFObject) {
    self.PFData = object
    
    guard let available = object[String.Event.available.rawValue] as? Int else {
      return nil
    }
    self.available = available
    
    guard let purchased = object[String.Event.purchased.rawValue] as? Int else {
      return nil
    }
    self.purchased = purchased
    
    ...
  }

  func soldOut() -> Bool {
     return purchased >= available
  }

}

From reading the initial docs and playground code, it seems like I can't just say

  guard let someVariable = object["someString"] as? Int else { return nil }

or even

anymore, without declaring

struct Event: ParseObject { 
  var someString: Int
  ... // another 20ish fields
}

and then changing it to

  let someVariable = Event.someString

with something on the order of 30 classes, and rapid changing of these classes, it seems like this is a huge amount of overhead just to add variables to a ParseObject? I'll read the evolution plan in a bit, but this is what I first gathered from looking at the docs - it seems like the final change would look something like


struct PFEvent: ParseObject { 
  
  static var className: String {
          "Event"
      }
  }
  var available: Int?
  var purchased: Int?
  ... // another 20ish fields
}

class Event {

  var PFData: PFEvent!

  var available: Int
  var purchased: Int
  ... // another 20ish fields
  
  init?(with object: PFEvent) {
    self.PFData = object
    
    guard let available = object.available as? Int else {
      return nil
    }
    self.available = available
    
    guard let purchased = object.purchased as? Int else {
      return nil
    }
    self.purchased = purchased
    
    ...
  }

  func soldOut() -> Bool {
     return purchased >= available
  }

}

@cbaker6
Copy link
Contributor

cbaker6 commented Oct 4, 2022

In your examples you are using strings as keys to access values, you are way more prone to errors compared to using properties or key paths (the Swift SDK), particularly when you have "rapid changing of these classes".

You don't need to force unwrap every property, depending on how you code, you can try get()

The README and the API docs state:

The ParseSwift SDK is not a port of the Parse-SDK-iOS-OSX SDK and though some of it may feel familiar, it is not backwards compatible and is designed using protocol oriented programming (POP) and value types instead of OOP and reference types. You can learn more about POP by watching Protocol-Oriented Programming in Swift or Protocol and Value Oriented Programming in UIKit Apps videos from previous WWDC’s. For more details about ParseSwift, visit the api documentation.

It's important to treat it as such. The Swift SDK doesn't derive from the Objective-C SDK. If you want similar behavior, you will need to create a separate SDK (that new SDK can possibly depend on the Swift SDK to reuse "some" code) and design it to behave with reference types and re-write the whole REST API layer. The other route would be to fix/improve the Objective-C SDK. I will not be able to assist with additional suggestions or designing for either of those routes as:

  1. I can't envision them being better, performing faster. or being more efficient than the Swift SDK
  2. I'm unwilling to invest any time due to my comments above

@atonylai
Copy link
Author

atonylai commented Oct 4, 2022

In your examples you are using strings as keys to access values, you are way more prone to errors compared to using properties or key paths (the Swift SDK), particularly when you have "rapid changing of these classes".

Not actually - as I stated in my original code snippet:

  guard let available = object[String.Event.available.rawValue] as? Int else {
      return nil
    }

Since we never in practice use object["available"] but only object[String.Event.available.rawValue] - this prevents errors due to mistyping a string since the compiler will catch it.

It's important to treat it as such. The Swift SDK doesn't derive from the Objective-C SDK.

I understand this, I was just answering your earlier comment on

I’m not sure what you mean by “a lot of work,”

because the two are completely different in design philosophy and architecture, having to write a lot of wrappers for each and every database class seems... a little heavy-handed?

But again, thank you for taking the time to reply! I appreciate it.

@atonylai atonylai closed this as completed Oct 4, 2022
@cbaker6
Copy link
Contributor

cbaker6 commented Oct 4, 2022

Since we never in practice use object["available"] but only object[String.Event.available.rawValue] - this prevents errors due to mistyping a string since the compiler will catch it.

If you really want to treat your ParseObject's as dictionaries instead of using key paths, you can see my response here as possible way.

@atonylai
Copy link
Author

atonylai commented Oct 4, 2022

Got it! Thank you so much!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question Support or code-level question
Projects
None yet
Development

No branches or pull requests

2 participants