iOS8错误:ABPersonViewController不显示属性&;后退按钮

iOS8错误:ABPersonViewController不显示属性&;后退按钮,ios8,abaddressbook,abpersonviewcontroller,Ios8,Abaddressbook,Abpersonviewcontroller,以下代码在iOS7中正常工作,但在iOS8中不能正常工作(变量recordID设置正确): iOS8中的bug: 当allowediting设置为YES时,会显示联系人,但 仅显示名称。导航栏左侧显示后退按钮(名为“地址”),右侧显示编辑按钮。当 按下编辑按钮,联系人显示为所有字段 除名称外为空,编辑按钮显示为“完成” 按钮如果按下此“完成”按钮之前未进行任何编辑, 将显示有关联系人的所有信息 当allowediting设置为NO时,不会显示后退按钮,因此 屏幕不能再留下 有人有解决办法吗 更新

以下代码在iOS7中正常工作,但在iOS8中不能正常工作(变量
recordID
设置正确):

iOS8中的bug:

  • allowediting
    设置为
    YES
    时,会显示联系人,但 仅显示名称。导航栏左侧显示后退按钮(名为“地址”),右侧显示编辑按钮。当 按下编辑按钮,联系人显示为所有字段 除名称外为空,编辑按钮显示为“完成” 按钮如果按下此“完成”按钮之前未进行任何编辑, 将显示有关联系人的所有信息
  • allowediting
    设置为
    NO
    时,不会显示后退按钮,因此 屏幕不能再留下
  • 有人有解决办法吗

    更新:


    到现在为止,我意识到问题1只有有时会发生在模拟器上,尽管总是发生在我的设备上

    更新:此黑客不再有效,完全无用(请参阅我的新答案)

    如果有人有上述相同的问题1),在苹果修复该漏洞之前,这里有一个非常肮脏的解决方法(我的漏洞报告仍然开放):
    由于在某些情况下需要在显示
    ABPersonViewController
    屏幕后切换编辑按钮两次,因此可以通过编程方式执行此操作:

    为显示
    ABPersoViewController
    UINavigationController定义一个属性:

    @property (nonatomic, strong) UINavigationController *  navigationControllerForPersonViewController;
    
    导航控制器显示person view控制器后,执行选择器进行切换:

    [self performSelector:@selector(toggleEditButton) withObject:nil afterDelay:0.7];  
    
    设置延迟,以便“个人视图控制器”屏幕可以显示动画。方法
    toggleEditButton
    定义为:

    - (void)toggleEditButton
    {
        UIBarButtonItem *editButton  = self.navigationControllerForPersonViewController.topViewController.navigationItem.rightBarButtonItem;
        id target = editButton.target;
        SEL editAction = editButton.action;
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [target performSelector:editAction withObject:editButton];
        [target performSelector:editAction withObject:editButton];
    #pragma clang diagnostic pop
    }
    
    需要使用#pragmas来抑制编译器对潜在内存泄漏的警告。
    结果是,person view controller的所有选定信息都会显示出来。

    montuno(再次感谢),他对我的第一个答案进行了评论,从苹果技术支持那里得到了如何解决第一个问题的提示,我现在也明白了第二个问题:

    1) 仅显示部分联系人:

    苹果声称以下代码是错误的:

    ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.addressBook     = addressBook;
    personViewController.displayedPerson = contactRef;
    CFRelease(addressBook);
    
    这里的
    地址簿
    在分配给
    ABPersonViewController
    后被错误释放

    在我的原始代码中,我没有
    CFRelease
    语句。但随后静态分析仪发出“地址簿中存储的对象可能泄漏”的警告“。插入发布语句后,生成成功,没有任何警告,因此我假设
    personViewController
    保留了
    地址簿
    ,情况显然不是这样,至少iOS8没有。我现在再次删除了发布语句,得到了警告,但一切正常

    2) 缺少后退按钮:
    ABPersonViewController
    的文档中说“重要人物视图控制器必须与导航控制器一起使用才能正常工作。”

    因此,我所做的如下:
    我设置了一个
    ABPersonViewController
    ,分配给它的
    navigationItem.BackbarButtonim
    a“完成”“按钮,并使用此
    personViewController
    初始化了一个新的
    UINavigationController
    ,使用
    initWithRootViewController:
    。然后我以模式呈现了新的
    navigationController

    显示带有后退按钮的
    personViewController
    ,按下后,演示视图控制器将取消模式演示的导航控制器。
    这在iOS<8上运行良好,但在iOS 8中,当
    allowsdediting
    设置为
    NO
    时,不会显示后退按钮

    但这显然不是苹果想要显示的
    personViewController


    我认为苹果假定
    navigationController
    已经存在,并呈现当前视图,因此新的
    personViewController
    被推到
    navigationController
    的堆栈上。在这种情况下,
    personViewController
    不是
    navigationC的
    rootViewController
    控制器
    ,导航控制器
    会自动显示一个后退按钮(对于
    rootViewController
    ),如果以这种方式实现,iOS8也可以正常工作。

    我在iOS8上也遇到了问题#1,仅在设备上(而不是在模拟器中)-虽然在我的情况下,我将allowsEditing设置为NO。您知道在禁用编辑时如何解决此问题吗?不幸的是,我不知道如何解决此问题。也许您也可以提交一份错误报告,以表明我不是唯一一个有此问题的人?仅供参考-Apple提供的演示源代码“QuickContacts”(可从Xcode中获得)演示如何使用ABPersonViewController。奇怪的是,它似乎在iOS 8上也能正常工作,甚至在设备上也是如此。然而,即使经过仔细分析,我也无法解释为什么我在自己的应用程序中会看到不同的行为。我不确定这是否可行,但如果新版本的ABPersonViewController使用未初始化的变量,那么e行为取决于其他代码在执行ABPersonViewController之前留下的内存,即有时可以工作,有时不工作。实际上,这发生在我随错误报告提交给苹果的一个小演示程序上。这个演示程序有时在模拟器中工作,但不总是,并且总是在设备上失败这可以解释我所看到的。解决第一个问题的方法对我也有帮助。但我有一点其他的情况:在第一次访问ABPersonViewController的addressBook属性之后,它会
    ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.addressBook     = addressBook;
    personViewController.displayedPerson = contactRef;
    CFRelease(addressBook);