mutableArrayValueForKey:countOf <key>未被调用,countOfSongs

时间:2015-08-11 20:49:58

标签: swift key-value-coding

我的确切问题在这里:

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

2 个答案:

答案 0 :(得分:2)

来自参考文章 http://www.cocoabuilder.com/archive/cocoa/236041-kvc-array-proxy-objects.html#236058

  

有关访问者搜索顺序的文档显示它会   更喜欢名为-<key>的方法而不是相应的-countOf<Key>和   - objectIn<Key>AtIndex:方法。

这意味着

let arrayProxy = playlist.mutableArrayValueForKey("songs")
let cnt = arrayProxy.count 

直接访问Playlist的“歌曲”属性,如果有的话 财产。

如果您重命名该属性,那么它按预期工作:

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

答案 1 :(得分:1)

对于未来的搜索者,这里是一个完整的例子,在OSX&gt;应用程序&gt;命令行工具中运行所有方法(我检查了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

我没有更多游乐场!