Swift - 访问 self 以避免将参数传递给函数

Swift - Access self to avoid passing parameters to a function

假设我有一个用户 class 发帖:

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

let myUser = User()

现在我想获取属于该用户的所有帖子,例如:

myUser.posts.fetchAllForUser(myUser.id)

但是,我想避免在 fetchAllForUser 中将 myUser.id 作为参数传递。如何访问 fetchAllForUser 中的 myUser.id,它由 posts 实现?

编辑: myUser.posts.fetchAllForUser(myUser.id) 的问题在于 fetchAllForUser 中的 self 实际上是 posts我需要像 self.self 这样的东西,但是 self.self 本身就是 self,哈哈;-)

此外,泛型 class Entities<T> 符合 Fetchable:

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

因为有人问我 - 这是 Fetchableintended 定义:

protocol Fetchable {
  associatedtype Element

  func fetchAllForUser(onSuccess: () -> [Element], onError: () -> Void) { ... }
}

看,我真的不想将 user.id 作为参数传递

如果我了解您的需求,这是一个可能的解决方案

型号

首先让我们定义您的模型

struct Post {
    let userID: String
}

struct User {
    let id: String
    let posts: [Post]

    init(id: String, posts:[Post]) {
        self.id = id
        self.posts = posts
    }
}

道​​

接下来您需要一个 class 从网络检索一些数据(例如 JSON 格式)并将该数据转换为 Post

final class Dao {
    static let sharedInstance = Dao()
    private init() { }

    func fetchUser(id:String, completion: (user: User?) -> ()) {

        // call webservice
        // convert NSData to JSON
        // extract id and posts from JSON
        // create User value

        // if everything goes fine then call completion(user)
        // else call comletion(nil)

    }

}

I suggest you SwiftyJson and Alamofire for the Dao implementation

用法

现在你可以写了

Dao.sharedInstance.fetchUser("1") { (user) in
    if let user = user {
        print(user.posts)
    }
}

与其尝试使用 self 访问用户,您可以简单地创建一个 EntitiesDelegate 协议,其中包含一个包含 Userid 的变量。此解决方案在 Cocoa Touch 中使用一种常见的设计模式,称为委托。

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

然后您将在 Entities class 中创建对 EntitiesDelegate 的引用,并更改 fetchAllForUser 方法的定义以具有 id参数默认为 nil。如果传入 id ,则可以使用它,但如果不是,则使用委托的 id 而不是使用 Nil Coalescing Operator(请注意,这也可能是 nil,所以如果两者都是 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
  }
}

然后您可以在 User class 中实现它,只需使其符合 EntitiesDelegate 协议即可。

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

就是这样!您现在可以简单地使用 myUser.posts.fetchAllForUser() 调用该方法,并且由于您的 User class 中已经有一个 id 变量,您甚至不需要更改任何内容使其符合EntitiesDelegate

如果您尝试遵循 Swift 3 种设计模式,您可能需要将方法签名更改为 func fetchAll(for id: Int = nil...),可以使用 myUser.posts.fetchAll()myUser.posts.fetchAll(for: 0) 当你想指定一个 id.