Dejell
Dejell

Reputation: 14317

Create class category with init method

I am trying to create a class category for UIActivityIndicatorView - I would like to set it in the screen center.

So I declared:

@implementation UIActivityIndicatorView(Normalize)

-(UIActivityIndicatorView *) setAtScreenCenter{
    CGRect r = [UIScreen mainScreen].applicationFrame;
    CGRect wheelR = CGRectMake(r.size.width / 2 - 12, r.size.height / 2 - 12, 24, 24);
    self = [[UIActivityIndicatorView alloc] initWithFrame:wheelR];
    self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
    self.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
                                      UIViewAutoresizingFlexibleRightMargin |
                                      UIViewAutoresizingFlexibleTopMargin |
                                      UIViewAutoresizingFlexibleBottomMargin);
    return self;
}
@end

Usage: [activityWheel setAtScreenCenter];

However, I get a compilation error:

Cannot assign to 'self' outside of a method in the init family

Upvotes: 1

Views: 1555

Answers (3)

rob mayoff
rob mayoff

Reputation: 385890

Your setAtScreenCenter is an instance message. You have to send it to an existing UIActivityIndicatorView. Why would you try to create a new UIActivityIndicatorView in this method?

Try this instead:

self.frame = wheelR;

You may also be rather confused about how coordinates work. The view's frame is relative to its superview's coordinate system. It's not relative to the screen coordinate system. Even if your superview is full screen, its coordinate system will be different from the screen's coordinate system in all but one orientation. You can convert the coordinates like this:

CGRect frame = [UIScreen mainScreen].applicationFrame;
CGPoint p = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
p = [self.window convertPoint:p fromWindow:nil]; // convert screen -> window
p = [self.superview convertPoint:p fromView:nil]; // convert window -> my superview
self.center = p;

Upvotes: 3

Hjalmar
Hjalmar

Reputation: 989

This is not really an init method. Therefore you should not assign to self here. Just skip that line and make the method a void method (no return value).

@implementation UIActivityIndicatorView(Normalize)

-(void) setAtScreenCenter{
    CGRect r = [UIScreen mainScreen].applicationFrame;
    CGRect wheelR = CGRectMake(r.size.width / 2 - 12, r.size.height / 2 - 12, 24, 24);
    self.frame = wheelR;
    self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
    self.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
                                      UIViewAutoresizingFlexibleRightMargin |
                                      UIViewAutoresizingFlexibleTopMargin |
                                      UIViewAutoresizingFlexibleBottomMargin);

}
@end

Now you can call it on an existing UIActivityIndicatorView to set its position like you wanted:

[activityWheel setAtScreenCenter];

Upvotes: 1

CodaFi
CodaFi

Reputation: 43330

The warning is more than just pedantry, the compiler is actually saving you from yourself. You should be declaring a new UIActivityIndicator var to return, instead of trying to assign to self. A better version of the method would look like this:

+(UIActivityIndicatorView *)setAtScreenCenter{
    CGRect r = [UIScreen mainScreen].applicationFrame;
    CGRect wheelR = CGRectMake(r.size.width / 2 - 12, r.size.height / 2 - 12, 24, 24);
    UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithFrame:wheelR];
    indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
    indicator.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
                                  UIViewAutoresizingFlexibleRightMargin |
                                  UIViewAutoresizingFlexibleTopMargin |
                                  UIViewAutoresizingFlexibleBottomMargin);
    return indicator;
}

As a class method, we no longer have to deal with assigning to self, and you can always be guaranteed to satisfy the return type of the method (if this were a true initializer, it would return id for easier subclassing).

Upvotes: 2

Related Questions