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 { ... }
因为有人问我 - 这是 Fetchable
的 intended 定义:
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
协议,其中包含一个包含 User
的 id
的变量。此解决方案在 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.
假设我有一个用户 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 { ... }
因为有人问我 - 这是 Fetchable
的 intended 定义:
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
协议,其中包含一个包含 User
的 id
的变量。此解决方案在 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.