成员引用基类型“类”不是结构或联合——Fixit 是不是将我引向了正确的方向?

Posted

技术标签:

【中文标题】成员引用基类型“类”不是结构或联合——Fixit 是不是将我引向了正确的方向?【英文标题】:Member reference base type 'Class' is not a structure or union - has the Fixit led me in the right direction?成员引用基类型“类”不是结构或联合——Fixit 是否将我引向了正确的方向? 【发布时间】:2017-03-31 23:53:36 【问题描述】:

我正在尝试创建一个delegate,它将在名为UIView 的自定义UIView 中发送来自UIButtons 的消息SGView,并且在错误消息之后有点超出我的深度。我最近学会了如何获得delegate to send messages successfully from within an instance method。

SGView 包含一个类方法,将多个UIButtons 排列成一个圆圈,旨在供不同的UIViews. The geometry works when the method is called from a parent UIView 使用。我现在通过在类方法声明中添加@protocol@property 来声明delegate

像这样......

SGView.h

#import <UIKit/UIKit.h>

@protocol SGViewDelegate <NSObject>
    -(void)buttonPressed:(UIButton*)button;
@end

@interface SGView : UIView 
    
    +(id)circleOfButtons:(int)buttonCount buttonSize:(CGFloat)buttonSize circleRadius:(CGFloat)circleRadius;

@property (assign) id<SGViewDelegate> delegate;

@end

SGView.m本质上是这样的

#import "SGView.h"

    @implementation SGView : UIView

    +(id)circleOfButtons:(int)buttonCount buttonSize:(CGFloat)buttonSize circleRadius:(CGFloat)circleRadius
    
    UIView *multipleViews       = [self new];

    // … circular geometry …

    [circleButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

    [multipleViews addSubview:circleButton];
    
    return multipleViews;
    
    @end

我在上面的目标操作语句中将目标从self更改为self.delegate的那一刻,Xcode报告了三个错误

'objc_class' 的定义必须从模块中导入 'ObjectiveC.runtime' 之前是必需的

“struct objc_class”中没有名为“delegate”的成员

成员引用类型'struct objc_class *'是一个指针;你的意思是 使用'->'?

Xcode 为最后一个提供了 Fixit

    Fixit Replace”.” with “->”

通过接受 Fixit,我删除了三个问题并引入了另一个

成员引用基类型“类”不是结构或联合

如果这个 Fixit 引导我朝着正确的方向前进,那么接下来我应该做什么?

在回到Apple documentation 和these tutorials 试图解决它之前,我需要问这个问题以弄清这个看似直截了当的问题。非常感谢任何帮助。谢谢。

解决方案

这可以在我对自己问题的回答中找到。

【问题讨论】:

【参考方案1】:

将类方法更改为实例方法似乎解决了我的问题。

这涉及将类方法 +(id)circleOfButtons:... etc 变成 .m.h 文件中的实例方法 (-(id)circleOfButtons:... etc)。还需要将父 UIView 中的调用从

    SGView *sgView              = [SGView circleOfButtons:count buttonSize:size circleRadius:radius];

    SGView *sgView              = [[SGView alloc] circleOfButtons:count buttonSize:size circleRadius:radius];

并将SGView 中的声明从

    UIView *multipleViews       = [self new];

    UIView *multipleViews       = [[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds];

SGView 现在可以从不同的UIViews 重复使用,这改变了UIButtons 的数量和大小排列成一个圆圈。 SGView 中的委托还允许每个按钮将标记消息发送到另一个类中的方法 - 在我的例子中是 ViewController.

完整的清单包含在下面,我欢迎其他在 OO 编程方面有更多经验的人提出建议或改进。

ViewController.h

#import <UIKit/UIKit.h>

    @interface ViewController : UIViewController <UIContentContainer> 
    
@end

ViewController.m

#import "ViewController.h"
#import "FamilyView.h"

@interface ViewController ()

@end

@implementation ViewController

    - (void)viewDidLoad                                             
    [super viewDidLoad];

    NSLog(@"load FamilyView");

    CGRect rect             = [UIScreen mainScreen].bounds;
    float  statusBarHeight  = [[UIApplication sharedApplication] statusBarFrame].size.height;
    CGRect screenFrame      = CGRectMake(0, statusBarHeight, rect.size.width, rect.size.height - statusBarHeight);
    self.view               = [[UIView alloc] initWithFrame: screenFrame];

    FamilyView *cv          = [[FamilyView alloc]initWithFrame:screenFrame];
    [self.view addSubview:cv];    



    - (void)buttonPressed:(UIButton*)button                          
    NSLog(@"Button %ld clicked.", (long int)[button tag]);

    switch (button.tag) 
        case 1:
        //            [self goToFamily1];
            break;
        case 2:
        //            [self goToFamily2];
            break;
        case 3:
        //            [self goToFamily3];
            break;
        case 4:
        //            [self goToFamily4];
            break;
        case 5:
        //            [self goToFamily5];
            break;
        default:
        //            [self goToHelp];
            break;
        
    
    @end

FamilyView.h

#import <UIKit/UIKit.h>
#import "ViewController.h"
#import "SGView.h"

    @interface FamilyView : UIView 
    
@end

FamilyView.m

#import <UIKit/UIKit.h>
#import "FamilyView.h"
#import "SGView.h"

    @implementation FamilyView : UIView

    - (id)initWithFrame:(CGRect)frame 
    self                                    = [super initWithFrame:[UIScreen mainScreen].bounds];
    if (self) 

    self.backgroundColor                    = [UIColor lightGrayColor];

    int     count                           = 5;  //16;
    CGFloat size                            = 80; //41;
    CGFloat radius                          = 68; //105;

    SGView *sgView                          = [[SGView alloc] circleOfButtons:count buttonSize:size circleRadius:radius];
    [self addSubview:sgView];
    
    return self;

@end

SGView.h

#import <UIKit/UIKit.h>

    @protocol SGViewDelegate <NSObject>
    -(void)buttonPressed:(UIButton*)button;
    @end

    @interface SGView : UIView 
    

      -(id)circleOfButtons:(int)buttonCount buttonSize:(CGFloat)buttonSize circleRadius:(CGFloat)circleRadius;

    @property (assign) id<SGViewDelegate> delegate;

    @end

SGView.m

#import "SGView.h"

    @implementation SGView : UIView

    -(id)circleOfButtons:(int)buttonCount buttonSize:(CGFloat)buttonSize circleRadius:(CGFloat)circleRadius
    
    UIView *multipleViews                   = [[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds];

    CGPoint screenCentre;
    CGPoint buttonCentre;

    screenCentre.x                          = CGRectGetWidth  ([UIScreen mainScreen].bounds) / 2;
    screenCentre.y                          = CGRectGetHeight ([UIScreen mainScreen].bounds) / 2;

    for (int i = 1; i <= buttonCount; i++) 
        CGFloat radians                     = 2 * M_PI * i / buttonCount;
        CGFloat arcStartPoint               = - M_PI / 2; // first point clockwise after 12 o'clock
        buttonCentre.x                      = screenCentre.x + circleRadius * cos(radians + arcStartPoint);
        buttonCentre.y                      = screenCentre.y + circleRadius * sin(radians + arcStartPoint);

        CGPoint target                      = CGPointMake(buttonCentre.x, buttonCentre.y);
        CGFloat x                           = screenCentre.x - buttonSize / 2;
        CGFloat y                           = screenCentre.y - buttonSize / 2;
        CGFloat wide                        = buttonSize;
        CGFloat high                        = buttonSize;
        UIButton *circleButton              = [[UIButton alloc] initWithFrame:CGRectMake(x, y, wide, high)];

        [circleButton setTag:i];
        [circleButton addTarget:self.delegate action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

        circleButton.clipsToBounds          = YES;
        circleButton.layer.masksToBounds    = NO;
        circleButton.layer.shadowOffset     = CGSizeMake(-15, 20);
        circleButton.layer.shadowRadius     = 5;
        circleButton.layer.shadowOpacity    = 0.0;
        circleButton.layer.borderWidth      = 0.25f;
        circleButton.layer.cornerRadius     = buttonSize/2;
        circleButton.layer.borderColor      = [UIColor blackColor].CGColor;
        circleButton.backgroundColor        = UIColor.whiteColor;
        [circleButton setTitle:[NSString stringWithFormat:@"%i", i] forState:UIControlStateNormal];

        if (buttonCount > 25) 
            [circleButton setTitleColor: [UIColor clearColor] forState:UIControlStateNormal];
             else 
            [circleButton setTitleColor: [UIColor grayColor] forState:UIControlStateNormal];
        

        [multipleViews addSubview:circleButton];

    // animation 1
        [UIView animateWithDuration:0.5 animations:^
        circleButton.transform              = CGAffineTransformMakeScale(1.0, 1.0);
        circleButton.center                 = screenCentre;
        
                     completion:^(BOOL finished)];

    // animation 2
        [UIView animateWithDuration:0.5f animations:^
        circleButton.transform              = CGAffineTransformIdentity;
        circleButton.center                 = target;
        
                     completion:^(BOOL finished)];
    
    return multipleViews;

@end

【讨论】:

以上是关于成员引用基类型“类”不是结构或联合——Fixit 是不是将我引向了正确的方向?的主要内容,如果未能解决你的问题,请参考以下文章

成员引用基类型“void”不是结构或联合 (OBJ-C)

错误:“double”不是类、结构或联合类型 [关闭]

目标 C 到 Swift 错误

添加字符串类型的类成员会导致调用基类函数而不是子类

crfoJkvKsm

自定义类型