0

I’m trying to make a delegate that will send messages from UIButtons within a custom UIView called SGView and am a bit out of my depth following the error messages. I recently learned how to get a delegate to send messages successfully from within an instance method.

SGView includes a class method that arranges multiple UIButtonsin a circle and was designed to be used by different UIViews. The geometry works when the method is called from a parent UIView. I have now declared the delegate by adding @protocol and @property to the class method declaration

like so ...

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 is essentially like this

#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

The moment I change the target from self to self.delegate in the target action statement above, Xcode reports three errors

Definition of 'objc_class' must be imported from module 'ObjectiveC.runtime' before it is required

No member named 'delegate' in 'struct objc_class'

Member reference type 'struct objc_class *' is a pointer; did you mean to use '->'?

Xcode offers a Fixit for the last of these

    Fixit Replace”.” with “->”

By accepting the Fixit I removed the three issues and introduced another

Member reference base type 'Class' is not a structure or union

If this Fixit has lead me in the right direction, what exactly should I be doing next ?

I need to ask this question to make sense of what might seem a straight forward problem before diving back into the Apple documentation and these tutorials trying to solve it. Any help is most appreciated. Thanks.

SOLUTION

This can be found in my answer to my own question.

4

1 回答 1

1

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

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

    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 编程方面有更多经验的人提出建议或改进。

视图控制器.h

#import <UIKit/UIKit.h>

    @interface ViewController : UIViewController <UIContentContainer> {
    }
@end

视图控制器.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

家庭视图.h

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

    @interface FamilyView : UIView {
    }
@end

家庭视图.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
于 2017-04-01T02:46:09.107 回答