mutableArrayValueForKey:countOf<Key> 未被调用,countOfSongs
mutableArrayValueForKey: countOf<Key> not being called, countOfSongs
我的确切问题在这里:
http://www.cocoabuilder.com/archive/cocoa/236041-kvc-array-proxy-objects.html#236058
I'm trying to understand how the proxy object which is returned from
mutableArrayValueForKey: works and I've hit a bit of a wall. I get
what the proxy is and why it exists. I have a test app which allows
me to do things to/with the collection it represents and it all works
fine. The problem is that when I try to implement some of the methods
mentioned in the developer docs under the "Key-Value Coding Accessor
Methods" section. There are some methods there which if implemented
in the hosting object (i.e. the original recipient of the
mutableArrayValueForKey: call) are to be called by the proxy when the
proxy is asked to do various things. The hitch is that in my test app
I can't get the -countOf<key> or -objectIn<key>AtIndex methods to be
invoked.
In reading through the docs, it seems that a number of methods need
to be implemented before any of these (dare I call them 'proxy
methods'?) are called. I implemented a whole slew of them - including
a number that shouldn't need to be - and ended up with this set: (The
test app is based on a Playlist->Songs->Song model where "songs" is
the NSMutableArray which lives in the Playlist class in which I'm
interested in getting a count of its member songs.)
- (unsigned int)countOfSongs;
- (Song *)objectInSongsAtIndex:(unsigned int)index;
- (NSArray *)songsAtIndexes:(NSIndexSet *)indexes;
- (void)getSongs:(Song **)buffer range:(NSRange)inRange;
- (void)insertObject:(Song *)newSong inSongsAtIndex:(unsigned int)idx;
- (void)removeObjectFromSongsAtIndex:(unsigned int)idx;
Even simple test code like this fails:
Playlist *myPlaylist = [[[Playlist alloc] init] autorelease];
id arrayProxy = [myPlaylist mutableArrayValueForKey:@"songs"];
[arrayProxy insertObject:[[[Song alloc] initWithName:@"test" andLength:
10] autorelease] atIndex:0];
unsigned int theCount = [arrayProxy count];
I've got all the properties defined, all the methods written, etc.
Yet when I call [arrayProxy count] my countOfSongs method in the
Playlist class isn't touched. The right answer is returned, but it's
apparently coming from the runtime going to the array directly and
getting the answer via NSArray's count method.
Oddly enough, when I do the insertObject call in line #3 the
insertObject:inSongsAtIndex: method IS called... so some of this stuff
works as I believe it is supposed to. Unfortunately it's the other
stuff that's driving me nuts. I've been working on this one for a
couple of days now and have tried everything I could come up with -
including some really silly, paranoid stuff - and have made no progress.
Can anybody help me with a suggestion as to what I might be doing
wrong or what I'm missing?
Thanks!
那里的答案——尽管它似乎对操作有所帮助——对我来说没有任何问题。
这是我的游乐场代码:
import Cocoa
"hello"
class Song {
dynamic var title = "Hello"
}
"hello"
class PlayList: NSObject {
/*dynamic*/ var songs = NSMutableArray()
//private var theSongs = NSMutableArray()
//var countOfSongs: Int = 100
func countOfSongs() -> Int {
println("count of songs")
return 100
//return theSongs.count + 100
}
func objectInSongsAtIndex(i: Int) -> AnyObject? {
println("getter")
return songs[i]
//return theSongs[i]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("insert")
songs[index] = song as! Song
//theSongs[index] = song as! Song
}
func removeObjectFromSongsAtIndex(index:Int) {
println("remove")
songs.removeObjectAtIndex(index)
//theSongs.removeObjectAtIndex(index)
}
}
"hello"
var playlist = PlayList()
"hello"
let arrayProxy = playlist.mutableArrayValueForKey("songs")
"hello"
arrayProxy.addObject(Song()) //successfully calls proxy method => outputs "insert"
arrayProxy.removeObjectAtIndex(0) //successfully calls proxy method => outputs "remove"
arrayProxy.count //=> 0 ???
我需要对我的代码进行哪些更改,以便在我编写时调用 countOfSongs 属性 或方法:
arrayProxy.count
来自参考文章
http://www.cocoabuilder.com/archive/cocoa/236041-kvc-array-proxy-objects.html#236058:
The documentation about accessor search order shows that it will
prefer a method named -<key>
over the corresponding -countOf<Key>
and
- objectIn<Key>AtIndex:
methods.
这意味着
let arrayProxy = playlist.mutableArrayValueForKey("songs")
let cnt = arrayProxy.count
直接访问Playlist
的"songs"属性,如果有的话
属性.
如果您重命名 属性,那么它将如您所愿地工作:
class Song {
dynamic var title = "Hello"
}
class PlayList: NSObject {
var thesongs = NSMutableArray()
func countOfSongs() -> Int {
println("count of songs")
return 100
}
func objectInSongsAtIndex(i: Int) -> AnyObject? {
println("getter")
return thesongs[i]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("insert")
thesongs[index] = song as! Song
}
func removeObjectFromSongsAtIndex(index:Int) {
println("remove")
thesongs.removeObjectAtIndex(index)
}
}
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
let cnt = arrayProxy.count
println(cnt)
输出:
count of songs
100
对于未来的搜索者,这里有一个完整的例子,在 OSX>Application>Command Line Tool(我检查了 Swift 的语言)中使用了所有方法:
import Foundation
class Song {
var title = "Hello"
}
class PlayList: NSObject {
private var array: [Song] = []
func countOfSongs() -> Int {
println("countOfSongs() called")
return array.count
}
/*
//This also works:
var countOfSongs: Int {
println("countOfSongs property was accessed")
return array.count
}
*/
func objectInSongsAtIndex(index: Int) -> AnyObject? {
println("getter called")
return array[index]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("inserting at index \(index)")
array.insert(song as! Song, atIndex: index)
}
func removeObjectFromSongsAtIndex(index:Int) {
println("removing at index \(index)")
array.removeAtIndex(index)
}
}
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
arrayProxy.addObject(Song())
println(arrayProxy.count)
arrayProxy.objectAtIndex(0)
arrayProxy.removeObjectAtIndex(0)
println(arrayProxy.count)
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
arrayProxy.addObject(Song())
println(arrayProxy.count)
arrayProxy.removeObjectAtIndex(0)
println(arrayProxy.count)
--output:--
countOfSongs() called
inserting at index 0
countOfSongs() called
1
getter called
removing at index 0
countOfSongs() called
0
我再也没有游乐场了!
我的确切问题在这里:
http://www.cocoabuilder.com/archive/cocoa/236041-kvc-array-proxy-objects.html#236058
I'm trying to understand how the proxy object which is returned from
mutableArrayValueForKey: works and I've hit a bit of a wall. I get
what the proxy is and why it exists. I have a test app which allows
me to do things to/with the collection it represents and it all works
fine. The problem is that when I try to implement some of the methods
mentioned in the developer docs under the "Key-Value Coding Accessor
Methods" section. There are some methods there which if implemented
in the hosting object (i.e. the original recipient of the
mutableArrayValueForKey: call) are to be called by the proxy when the
proxy is asked to do various things. The hitch is that in my test app
I can't get the -countOf<key> or -objectIn<key>AtIndex methods to be
invoked.
In reading through the docs, it seems that a number of methods need
to be implemented before any of these (dare I call them 'proxy
methods'?) are called. I implemented a whole slew of them - including
a number that shouldn't need to be - and ended up with this set: (The
test app is based on a Playlist->Songs->Song model where "songs" is
the NSMutableArray which lives in the Playlist class in which I'm
interested in getting a count of its member songs.)
- (unsigned int)countOfSongs;
- (Song *)objectInSongsAtIndex:(unsigned int)index;
- (NSArray *)songsAtIndexes:(NSIndexSet *)indexes;
- (void)getSongs:(Song **)buffer range:(NSRange)inRange;
- (void)insertObject:(Song *)newSong inSongsAtIndex:(unsigned int)idx;
- (void)removeObjectFromSongsAtIndex:(unsigned int)idx;
Even simple test code like this fails:
Playlist *myPlaylist = [[[Playlist alloc] init] autorelease];
id arrayProxy = [myPlaylist mutableArrayValueForKey:@"songs"];
[arrayProxy insertObject:[[[Song alloc] initWithName:@"test" andLength:
10] autorelease] atIndex:0];
unsigned int theCount = [arrayProxy count];
I've got all the properties defined, all the methods written, etc.
Yet when I call [arrayProxy count] my countOfSongs method in the
Playlist class isn't touched. The right answer is returned, but it's
apparently coming from the runtime going to the array directly and
getting the answer via NSArray's count method.
Oddly enough, when I do the insertObject call in line #3 the
insertObject:inSongsAtIndex: method IS called... so some of this stuff
works as I believe it is supposed to. Unfortunately it's the other
stuff that's driving me nuts. I've been working on this one for a
couple of days now and have tried everything I could come up with -
including some really silly, paranoid stuff - and have made no progress.
Can anybody help me with a suggestion as to what I might be doing
wrong or what I'm missing?
Thanks!
那里的答案——尽管它似乎对操作有所帮助——对我来说没有任何问题。
这是我的游乐场代码:
import Cocoa
"hello"
class Song {
dynamic var title = "Hello"
}
"hello"
class PlayList: NSObject {
/*dynamic*/ var songs = NSMutableArray()
//private var theSongs = NSMutableArray()
//var countOfSongs: Int = 100
func countOfSongs() -> Int {
println("count of songs")
return 100
//return theSongs.count + 100
}
func objectInSongsAtIndex(i: Int) -> AnyObject? {
println("getter")
return songs[i]
//return theSongs[i]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("insert")
songs[index] = song as! Song
//theSongs[index] = song as! Song
}
func removeObjectFromSongsAtIndex(index:Int) {
println("remove")
songs.removeObjectAtIndex(index)
//theSongs.removeObjectAtIndex(index)
}
}
"hello"
var playlist = PlayList()
"hello"
let arrayProxy = playlist.mutableArrayValueForKey("songs")
"hello"
arrayProxy.addObject(Song()) //successfully calls proxy method => outputs "insert"
arrayProxy.removeObjectAtIndex(0) //successfully calls proxy method => outputs "remove"
arrayProxy.count //=> 0 ???
我需要对我的代码进行哪些更改,以便在我编写时调用 countOfSongs 属性 或方法:
arrayProxy.count
来自参考文章 http://www.cocoabuilder.com/archive/cocoa/236041-kvc-array-proxy-objects.html#236058:
The documentation about accessor search order shows that it will prefer a method named
-<key>
over the corresponding-countOf<Key>
and- objectIn<Key>AtIndex:
methods.
这意味着
let arrayProxy = playlist.mutableArrayValueForKey("songs")
let cnt = arrayProxy.count
直接访问Playlist
的"songs"属性,如果有的话
属性.
如果您重命名 属性,那么它将如您所愿地工作:
class Song {
dynamic var title = "Hello"
}
class PlayList: NSObject {
var thesongs = NSMutableArray()
func countOfSongs() -> Int {
println("count of songs")
return 100
}
func objectInSongsAtIndex(i: Int) -> AnyObject? {
println("getter")
return thesongs[i]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("insert")
thesongs[index] = song as! Song
}
func removeObjectFromSongsAtIndex(index:Int) {
println("remove")
thesongs.removeObjectAtIndex(index)
}
}
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
let cnt = arrayProxy.count
println(cnt)
输出:
count of songs 100
对于未来的搜索者,这里有一个完整的例子,在 OSX>Application>Command Line Tool(我检查了 Swift 的语言)中使用了所有方法:
import Foundation
class Song {
var title = "Hello"
}
class PlayList: NSObject {
private var array: [Song] = []
func countOfSongs() -> Int {
println("countOfSongs() called")
return array.count
}
/*
//This also works:
var countOfSongs: Int {
println("countOfSongs property was accessed")
return array.count
}
*/
func objectInSongsAtIndex(index: Int) -> AnyObject? {
println("getter called")
return array[index]
}
func insertObject(song:AnyObject, inSongsAtIndex index:Int) {
println("inserting at index \(index)")
array.insert(song as! Song, atIndex: index)
}
func removeObjectFromSongsAtIndex(index:Int) {
println("removing at index \(index)")
array.removeAtIndex(index)
}
}
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
arrayProxy.addObject(Song())
println(arrayProxy.count)
arrayProxy.objectAtIndex(0)
arrayProxy.removeObjectAtIndex(0)
println(arrayProxy.count)
var playlist = PlayList()
let arrayProxy = playlist.mutableArrayValueForKey("songs")
arrayProxy.addObject(Song())
println(arrayProxy.count)
arrayProxy.removeObjectAtIndex(0)
println(arrayProxy.count)
--output:--
countOfSongs() called
inserting at index 0
countOfSongs() called
1
getter called
removing at index 0
countOfSongs() called
0
我再也没有游乐场了!