Подтвердить что ты не робот

UIPopover presentFromBarButton вне центра

Я заметил в проекте, что позиционирование popover над элементом правой кнопки панели кажется по праву по какой-то причине. Я попробовал вместо этого использовать UIButton для пользовательского представления, а затем представляю popover из этой кнопки, но popover, кажется, игнорирует showFromRect, если я действительно предоставляю ему "центрированное" значение.

Off-center popover

Этот код довольно прост:

- (void)viewDidLoad {
    [super viewDidLoad];

     UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"share"] style:UIBarButtonItemStylePlain target:self action:@selector(shareTap:)];

     self.navigationItem.rightBarButtonItem = button;
}

- (void)shareTap:(UIBarButtonItem *)button {
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]];

    [self.popover presentPopoverFromBarButtonItem:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

Теперь, если я переключусь на использование внутренней кнопки, как уже упоминалось, я вижу подобное поведение (изменение цвета заметки, так что изображение появляется).

using internal button

Код для этого довольно простой:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *innerButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
    [innerButton setImage:[UIImage imageNamed:@"share"] forState:UIControlStateNormal];
    [innerButton addTarget:self action:@selector(shareTap:) forControlEvents:UIControlEventTouchUpInside];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:innerButton];;
}

- (void)shareTap:(UIButton *)button {
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]];

//    CGRect bottomCenter = CGRectMake(button.frame.size.width / 2, button.frame.size.height, 1, 1);
    CGRect bottomCenter = CGRectMake(2, button.frame.size.height, 1, 1);

    [self.popover presentPopoverFromRect:bottomCenter inView:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

Обратите внимание, что вместо того, чтобы использовать фактический центр, я использовал произвольное значение. 2. Если я использую 1 или 0, popover становится выровненным по левому краю. Все, что больше одного, снова выровнено по правому краю.

left-aligned

Я немного искал поиск аналогичного вопроса, но я не могу найти никого с той же проблемой. Любая идея вокруг того, что вызывает это и как ее избежать, будет весьма признательна. Единственное, на что я мог догадаться, - это то, что из-за своей близости к краю Apple делает некоторое позиционирование вуду, чтобы заставить его быть там, где они этого хотят. Проблема в том, что кнопка в правом верхнем углу выглядит как довольно стандартная выпадающая позиция.

Изменить: я подтвердил, что такое же поведение происходит при длительном нажатии на значок "Новое сообщение" в приложении родной почты.

Изменить 2: Я смог подтвердить Apple, что это проблема. В одной из последних версий (я не могу вспомнить, какой из них я думаю), они сделали это так, чтобы вы могли вручную установить это. Поведение по умолчанию все еще не так. Я верю (я не пробовал это некоторое время), но вы можете использовать метод смещения CGRect, чтобы заставить его работать правильно, если вы так наклонены.

4b9b3361

Ответ 1

Здесь один из способов сделать это: вместо использования UIBarButtonSystemItem используйте UIBarButtonItem с пользовательским представлением. Просто перетащите UIButton в UINavigationBar, чтобы получить UIBarButtonItem со встроенным UIButton, который отображается как UIBarButtonItem customView.

@IBAction func didTapActionButton(_ sender: Any) {
    if let vc = self.storyboard?.instantiateViewController(withIdentifier: "myPopover") {
        vc.modalPresentationStyle = .popover
        guard let innerView = actionButton.customView else {
            // Unexpected missing custom view
            return
        }

        vc.popoverPresentationController?.sourceView = navigationController?.navigationBar
        vc.popoverPresentationController?.sourceRect = innerView.frame
        self.present(vc, animated: true, completion: nil)
    }
}

Ответ 2

Вы должны указать рамку кнопки на панели, из которой должен отображаться поп.

В следующем коде представлен символ UIAlertController в виде popover из панели.

    @IBOutlet weak var playerRightBarButton: UIBarButtonItem!

    extension UIBarButtonItem {
       var frame: CGRect? {
        guard let view = self.value(forKey: "view") as? UIView else {
          return nil
      }
      return view.frame
    }
  }

    let alert = UIAlertController(title: "", message: "Sample PopOver", 
    preferredStyle: .actionSheet)
    if alert.responds(to: #selector(getter: popoverPresentationController)) {
            alert.popoverPresentationController?.sourceView = self.view
            alert.popoverPresentationController?.barButtonItem = playerRightBarButton
            alert.popoverPresentationController?.permittedArrowDirections = .up
            if let frame = playerRightBarButton.frame {
                alert.popoverPresentationController?.sourceRect = frame
            }
        }
        self.present(alert, animated: true, completion: nil)