尝试单元测试我在导航栏按钮上设置了正确的UIBarButtonSystemItem。
我可以恢复风格,但似乎无法找到获取UIBarButtonSystemItem的方法
为按钮设置的枚举。由于样式与
不同,因此失败UIBarButtonSystemItem:
- (void)test_init_should_set_left_right_barButtonItems {
UIBarButtonItem *left = mainVCSUT.navigationItem.leftBarButtonItem;
UIBarButtonItem *right = mainVCSUT.navigationItem.rightBarButtonItem;
[Assert isNotNil:left];
[Assert isNotNil:right];
UIBarButtonItemStyle leftStyle = left.style;
UIBarButtonItemStyle rightStyle = right.style;
[Assert that:[The int:leftStyle] is:[Equal to:[The int:UIBarButtonSystemItemRefresh]]];
[Assert that:[The int:rightStyle] is:[Equal to:[The int:UIBarButtonSystemItemSearch]]];
}
答案 0 :(得分:17)
至少在iOS 6.1上(我还没有测试过其他版本)UIBarButtonItem
有一个未声明的方法systemItem
,它返回传入初始化程序的值。您可以使用键值编码轻松访问它:
UIBarButtonSystemItem systemItemIn = UIBarButtonSystemItemAdd;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItemIn target:nil action:NULL];
NSNumber *value = [item valueForKey:@"systemItem"];
UIBarButtonSystemItem systemItemOut = [value integerValue];
NSLog(@"systemItemIn = %d, systemItemOut = %d", systemItemIn, systemItemOut);
如果这不起作用,您可以为内部匿名结构创建一个typedef,它是存储此信息的UIBarButtonItem
类的实例变量,并使用私有ivar的名称和Objective C运行时,如下图所示:
//Copied from UIBarButtonItem.h, this is the struct used for the _barButtomItemFlags ivar
typedef struct {
unsigned int enabled:1;
unsigned int style:3;
unsigned int isSystemItem:1;
unsigned int systemItem:7;
unsigned int viewIsCustom:1;
unsigned int isMinibarView:1;
unsigned int disableAutosizing:1;
unsigned int selected:1;
unsigned int imageHasEffects:1;
} FlagsStruct;
// In our test code
// Instantiate a bar button item
UIBarButtonSystemItem systemItemIn = UIBarButtonSystemItemAdd;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItemIn target:nil action:NULL];
// Set up variables needed for run time functions
Class barItemClass = [item class];
BOOL foundIt = NO; // We check this flag to make sure we found the ivar we were looking for
ptrdiff_t ivarOffset = 0; // This will be the offset of _barButtomItemFlags within the bar button item object
// Iterate through all of UIBarButtonItem's instance variables
unsigned int ivarCount = 0;
Ivar *ivarList = class_copyIvarList(barItemClass, &ivarCount);
for (int i = 0; i < ivarCount; i++) {
Ivar ivar = ivarList[i];
const char *ivarName = ivar_getName(ivar);
if (!strcmp(ivarName, "_barButtonItemFlags")) {
// We've found an ivar matching the name. We'll get the offset and break from the loop
foundIt = YES;
ivarOffset = ivar_getOffset(ivar);
break;
}
}
free(ivarList);
if (foundIt) {
// Do a little pointer math to get the FlagsStruct - this struct contains the system item value.
void *itemPointer = (__bridge void *)item;
FlagsStruct *flags = itemPointer + ivarOffset;
UIBarButtonSystemItem systemItemOut = flags->systemItem;
NSLog(@"systemItemIn = %d, systemItemOut = %d", systemItemIn, systemItemOut);
BOOL equal = (systemItemIn == systemItemOut);
if (equal) {
NSLog(@"yes they are equal");
}
else {
NSLog(@"no they are not");
}
}
else {
// Perhaps Apple changed the ivar name?
NSLog(@"didn't find any such ivar :(");
}
无论你接近它,它都可能会改变,所以我建议你的测试只能在经过验证支持这些方法的操作系统版本上有条件地运行。