簡體   English   中英

UIControl 子類 - 按下時顯示 UIMenu

[英]UIControl subclass - show UIMenu when pressing

摘要:我想要做的就是擁有一個 UIControl 子類,它在按下時顯示 UIMenu,我已經閱讀了另一個問題,但是在將 contextMenuinteractionEnabled 屬性設置為 YES 時我遇到了崩潰。

類似問題: iOS 14 Context Menu from UIView (Not from UIButton or UIBarButtonItem)


我有一個 UIControl 子類,我想向它添加一個菜單,並在單擊控件時顯示 UIMenu。 但是在將 contextMenuInteractionEnabled 屬性設置為 YES 時,我一直收到錯誤消息。

這是控件子類:

@interface MyControl : UIControl
@end

@implementation MyControl
@end

它只是一個普通的 UIControl 子類。 然后,我創建了該 class 的實例並將 contextMenuInteractionEnabled 的值設置為 YES,如下所示:

MyControl *myControl = [[MyControl alloc] init];
myControl.contextMenuInteractionEnabled = YES; //<-- Thread 1: "Invalid parameter not satisfying: interaction"

但是當運行它時,我收到以下錯誤消息:

錯誤信息

***斷言失敗-[MyControl addInteraction:], UIView.m:17965

*** 由於未捕獲的異常“NSInternalInconsistencyException”而終止應用程序,原因:“無效參數不滿足:交互”

錯誤:NSInternalInconsistencyException

原因:無效參數不滿足:交互

堆棧跟蹤: (

0 核心基礎 0x00000001b8181e94 5CDC5D9A-E506-3740-B64E-BB30867B4F1B + 40596

1 libobjc.A.dylib 0x00000001b14b78d8 objc_exception_throw + 60

2 基金會 0x00000001b2aa5b4c C431ACB6-FE04-3D28-B677-4DE6E1C7D81F + 5528396

3 UIKitCore 0x00000001ba47e5bc 179501B6-0FC2-344A-B969-B4E3961EBE10 + 1349052

4 UIKitCore 0x00000001ba47ea70 179501B6-0FC2-344A-B969-B4E3961EBE10 + 1350256

)

libc++abi:以 NSException 類型的未捕獲異常終止

*** 由於未捕獲的異常“NSInternalInconsistencyException”而終止應用程序,原因:“無效參數不滿足:交互”以 NSException 類型的未捕獲異常終止


問題

  1. 錯誤消息“無效參數不滿足:交互”是什么意思? “互動”從何而來,如何解決?

  2. 我究竟做錯了什么? 我想要的只是一個可以在按下時顯示菜單的自定義 UIControl。 就是這樣。

作為旁注,此代碼適用於 UIButton 實例,因此 UIButton class 正在做我沒有做的內部事情,但我不知道是什么。

更新 1

根據@DonMag 的回答,我嘗試了這個:

    MyControl *control = [[MyControl alloc] init];
    control.showsMenuAsPrimaryAction = YES;

    UIContextMenuInteraction *contextMenuInteraction = [[UIContextMenuInteraction alloc] initWithDelegate:self];
    [control addInteraction:contextMenuInteraction];

    [self.view addSubview:control];

這不再崩潰,如果我長按它甚至會顯示菜單。 但我希望它能像常規菜單一樣顯示,作為按下控件的主要操作。 我想要做的是模擬 UIButton 上的menu屬性。如果我可以實現一個具有菜單屬性的控件,然后讓該菜單作為主要操作可用,那將是最理想的事情。

無需調用.contextMenuInteractionEnabled = YES; ...

這是一個快速、完整的示例:

#import <UIKit/UIKit.h>

@interface MyControl : UIControl
@end

@implementation MyControl
@end

@interface ControlMenuViewController : UIViewController <UIContextMenuInteractionDelegate>
@end

@interface ControlMenuViewController ()
@end

@implementation ControlMenuViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    MyControl *myControl = [MyControl new];

    UIContextMenuInteraction *interaction = [[UIContextMenuInteraction alloc] initWithDelegate:self];
    [myControl addInteraction:interaction];
    
    myControl.frame = CGRectMake(100, 200, 200, 50);
    myControl.backgroundColor = UIColor.systemRedColor;
    [self.view addSubview:myControl];
    
}

- (nullable UIContextMenuConfiguration *)contextMenuInteraction:(nonnull UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location {
    
    UIContextMenuConfiguration* config = [UIContextMenuConfiguration configurationWithIdentifier:nil
                                                                                 previewProvider:nil
                                                                                  actionProvider:^UIMenu* _Nullable(NSArray<UIMenuElement*>* _Nonnull suggestedActions) {
        
        NSMutableArray* actions = [[NSMutableArray alloc] init];
        
        [actions addObject:[UIAction actionWithTitle:@"Stand!" image:[UIImage systemImageNamed:@"figure.stand"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Stand!");
            //[self performMenuCommandStand];
        }]];
        [actions addObject:[UIAction actionWithTitle:@"Walk!" image:[UIImage systemImageNamed:@"figure.walk"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Walk!");
            //[self performMenuCommandWalk];
        }]];
        [actions addObject:[UIAction actionWithTitle:@"Run!" image:[UIImage systemImageNamed:@"figure.run"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Run!");
            //[self performMenuCommandRun];
        }]];
        
        UIMenu* menu = [UIMenu menuWithTitle:@"" children:actions];
        return menu;
        
    }];
    
    return config;

}

@end

編輯

稍作修改以允許單擊(主要操作):

#import <UIKit/UIKit.h>

@interface MyControl : UIControl
@property (strong, nonatomic) UIContextMenuConfiguration *menuCfg;
@end

@implementation MyControl
- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location {
    return self.menuCfg;
}
@end

@interface ControlMenuViewController : UIViewController
@end

@interface ControlMenuViewController ()
@end

@implementation ControlMenuViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    MyControl *myControl = [MyControl new];
    
    myControl.frame = CGRectMake(100, 200, 200, 50);
    myControl.backgroundColor = UIColor.systemRedColor;
    [self.view addSubview:myControl];

    // menu configuration
    UIContextMenuConfiguration* config = [UIContextMenuConfiguration configurationWithIdentifier:nil
                                                                                 previewProvider:nil
                                                                                  actionProvider:^UIMenu* _Nullable(NSArray<UIMenuElement*>* _Nonnull suggestedActions) {
        
        NSMutableArray* actions = [[NSMutableArray alloc] init];
        
        [actions addObject:[UIAction actionWithTitle:@"Stand!" image:[UIImage systemImageNamed:@"figure.stand"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Stand!");
            //[self performMenuCommandStand];
        }]];
        [actions addObject:[UIAction actionWithTitle:@"Walk!" image:[UIImage systemImageNamed:@"figure.walk"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Walk!");
            //[self performMenuCommandWalk];
        }]];
        [actions addObject:[UIAction actionWithTitle:@"Run!" image:[UIImage systemImageNamed:@"figure.run"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) {
            NSLog(@"Run!");
            //[self performMenuCommandRun];
        }]];
        
        UIMenu* menu = [UIMenu menuWithTitle:@"" children:actions];
        return menu;
        
    }];

    // set custom control menu configuration
    myControl.menuCfg = config;
    
    // show menu on single-tap (instead of long-press)
    [myControl setContextMenuInteractionEnabled:YES];
    myControl.showsMenuAsPrimaryAction = YES;
    
}

@end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM