lustoykov lustoykov - 3 months ago 6
Swift Question

Swift - Access self to avoid passing parameters to a function

Let's say I have an User class with Posts:

class User {
internal var id: Int
internal var posts: Entities<Post>
}

let myUser = User()


Now I want to fetch all posts that belong to this user, something like:

myUser.posts.fetchAllForUser(myUser.id)


However, I want to avoid passing
myUser.id
as a parameter in
fetchAllForUser
. How can I access
myUser.id
in
fetchAllForUser
, which is implemented by
posts
?

EDIT:
The problem with
myUser.posts.fetchAllForUser(myUser.id)
is that the
self
in
fetchAllForUser
would be actually
posts
. I need something like
self.self
, but
self.self
is
self
itself
, lol;-)

Moreover, the generic class
Entities<T>
conforms to
Fetchable
:

class Entities<Element> : Fetchable { ... }


Because I was asked - here is what the intended definition of
Fetchable
would be like:

protocol Fetchable {
associatedtype Element

func fetchAllForUser( ... ) { ... }
}


See, I don't really want to pass the user.id as a param

Answer

Instead of trying to access the user with self, you could simply make an EntitiesDelegate protocol that has a variable containing the User's id.

protocol EntitiesDelegate {
  var id: String {get set}
}

You would then create a reference to an EntitiesDelegate inside of your Entities class, and change the fetchAllForUser method's definition to have the id argument as nil by default. If the id is passed in, you can use it, but if it isn't, use the delegate's id instead using the Nil Coalescing Operator (note that this may be nil too, so maybe throw an error if both are nil)

class Entities<Element> : Fetchable {
  var delegate: EntitiesDelegate?

  func fetchAllForUser(id: Int = nil, onSuccess: () -> [Element], onError: () -> Void) {
    guard let idToUse = id ?? delegate?.id else {
      return //Maybe throw an error here
    } 
    //Use idToUse from here on
  }
}

You can then implement this in your User class by simply making it conform to the EntitiesDelegate protocol.

class User: EntitiesDelegate {
  ...
  init(...) {
    ...
    posts.delegate = self
  }
}

And that's it! Simply remember to replace all references to the id argument with idToUse in your fetchAllForUser method, and you should not need to change any other code.

Comments