@Ilija:如果你发帖说你已经放下了,那么你其实还没有真正放下。 ;) 让我看看我能否澄清
我的评论:
-(NSString *) album
{
return self->album;
}
-(NSDictionary *) albumAndArtist
{
return @{ @"album":self.album, @"artist":self.artist };
}
上面的
album
方法是Objective-C编译器会自动生成的。而
albumAndArtist
方法则是我在回答你原始问题时建议的。现在,如果你让Clang将这两个方法转换成C语言(
clang -rewrite-objc test.m -o test.cc
),你会得到类似下面的代码:
static NSDictionary * _I_iTunesTrack_albumAndArtist_albumAndArtist(iTunesTrack * self, SEL _cmd) {
return ((NSDictionary *(*)(id, SEL, const id *, const id *, NSUInteger))(void *)
objc_msgSend)(objc_getClass("NSDictionary"), sel_registerName("dictionaryWithObjects:forKeys:count:"),
(const id *)__NSContainer_literal(2U, ((NSString *(*)(id, SEL))(void *)objc_msgSend)
((id)self, sel_registerName("album")), ((NSString *(*)(id, SEL))(void *)objc_msgSend)
((id)self, sel_registerName("artist"))).arr, (const id *)__NSContainer_literal(2U,
(NSString *)&__NSConstantStringImpl_test_m_0, (NSString *)&__NSConstantStringImpl_test_m_1).arr, 2U);
}
或者用人类的语言来说,
-(NSDictionary *) albumAndArtist
{
id album = objc_msgSend(self, sel_registerName("album"));
id artist = objc_msgSend(self, sel_registerName("artist"));
id *values = calloc(2, sizeof(id)); values[0] = album; values[1] = artist;
id *keys = calloc(2, sizeof(id)); keys[0] = @"album"; keys[1] = @"artist";
Class dict_class = objc_getClass("NSDictionary");
id result = objc_msgSend(dict_class, sel_registerName("dictionaryWithObjects:forKeys:count:"), values, keys, 2);
free(values); free(keys);
return result;
}
看看这个:三个sel_registerName
,一个objc_getClass
,三个objc_msgSend
,两个calloc
和两个free
。与编译器生成的album
方法相比,这相当低效。
Technically, the compiler-generated album
method looks like this:
-(NSString *) album
{
return objc_getProperty(self, _cmd,
__OFFSETOFIVAR__(struct iTunesTrack, album), /*atomic*/ YES);
}
but that's only because it wasn't originally declared as nonatomic
. For the meaning of objc_getProperty
, see here; but basically, it's faster than an objc_msgSend
would have been.)
很明显,albumAndArtist
比 album
要慢得多,因为它要做更多的额外工作。但是——你会问——如果我们摆脱所有这些工作,只返回 self.album
呢?那么,生成的代码仍然比编译器为 album
getter 生成的代码更复杂:
-(NSString *) albumAndArtist_stripped_down
{
// return self.album;
return objc_msgSend(self, sel_registerName("album"));
}
当你的程序调用
myTrack.album
时,它会调用
objc_msgSend
一次来确定它应该调用
album
方法,然后在
album
内部调用
objc_getProperty
。这是两个调用。(如果您计算
selector_registerName("album")
,则为三个调用。)
当您的程序调用
myTrack.albumAndArtist_stripped_down
时,它会调用
objc_msgSend
一次来确定它应该调用
albumAndArtist_stripped_down
方法,然后
那个调用
objc_msgSend
第二次,然后
那个调用
objc_getProperty
。这是三个调用。(如果您计算
selector_registerName
,则为五个调用。)
因此,对我来说,
albumAndArtist_stripped_down
大约应该比单独的
album
慢两倍(或5/3倍)。
至于原始的
albumAndArtist
,仅通过计算函数调用次数,我预计它的速度将比
album
慢五倍左右...但当然它会比那慢得多,因为它至少进行了三次内存分配,而
album
没有进行任何内存分配。内存分配和清理非常昂贵,因为
malloc
本身就是一个复杂的算法。
希望这能为您解决问题。 :)
albumAndArtist
属性,然后使用 KVC 来获取所有不同的键值对。 - ughoavgfhw