views:

65

answers:

3

I do this quite a bit in my code:

        self.sliderOne.frame  = CGRectMake(newX, 0, self.sliderOne.frame.size.width, self.sliderOne.frame.size.height); 

Is there any way to avoid this tedious code? I have tried this type of thing:

  self.sliderOne.frame.origin.x = newX;

but I get a Lvalue required as left operand of assignment error.

+1  A: 

The issue here is that self.sliderOne.frame.origin.x is the same thing as [[self sliderOne] frame].origin.x. As you can see, assigning back to the lValue here is not what you want to do.

So no, that "tedious" code is necessary, although can be shortened up a bit.

CGRect rect = thing.frame;
thing.frame = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect) + 10, etc...);
Joshua Weinberg
Is it shorter because you used a variable? I'm missing something, I think.
Yar
Just cleaner in my opinion
Joshua Weinberg
+1  A: 

Yeah, you have to do:

CGRect newFrame = self.sliderOne.frame;
newFrame.origin.x = frame.size.width - MARGIN * 2 - totalWidth;
self.sliderOne.frame = newFrame;

It sucks, I know. If you find yourself doing this a lot, you may want to add categories to UIView/NSView to alter this stuff for you:

@interface UIView (FrameMucking)

- (void) setWidth:(CGFloat)newWidth;

@end

@implementation UIView (FrameMucking)
 - (void) setWidth:(CGFloat)newWidth {
  CGRect f = [self frame];
  f.size.width = newWidth;
  [self setFrame:f];
}
@end

Etc.

Dave DeLong
Wow. I didn't know categories are the objective-c (or C?) mechanism for monkey patching. Very interesting.
Yar
@yar they are a mechanism, and they're one of my most favorite Objective-C language features. :)
Dave DeLong
wow I just noticed that you're saying that you can set the width using `f.size.width=`... I hope that's true.
Yar
@Daniel `f` is a C structure, which means `f.size.width = 42` will change a variable that's being stored locally. You then have to apply those changes into the UIView via `setFrame:`, which wants a structure as the parameter. I've done this dozens of times.
Dave DeLong
@Dave DeLong: what I don't get is why I am allowed to change f.size.width and not able to change self.frame.size.width... that's the heart of the question.
Yar
@Dave DeLong, I took your lead and wrote up the AlterFrame category below. Very cool.
Yar
A: 

I finally followed @Dave DeLong's suggestion and made a category. All you have to do is import it in any class that wants to take advantage of it. XCode even knows about it!

AlterFrame.h

#import <UIKit/UIKit.h>

@interface UIView (AlterFrame)

- (void) setFrameWidth:(CGFloat)newWidth;
- (void) setFrameHeight:(CGFloat)newHeight;
- (void) setFrameOriginX:(CGFloat)newX;
- (void) setFrameOriginY:(CGFloat)newY;

@end

AlterFrame.m

#import "AlterFrame.h"

@implementation UIView (AlterFrame)

    - (void) setFrameWidth:(CGFloat)newWidth {
        CGRect f = self.frame;
        f.size.width = newWidth;
        self.frame = f;
    }

    - (void) setFrameHeight:(CGFloat)newHeight {
        CGRect f = self.frame;
        f.size.height = newHeight;
        self.frame = f;
    }

    - (void) setFrameOriginX:(CGFloat)newX {
        CGRect f = self.frame;
        f.origin.x = newX;
        self.frame = f;
    }

    - (void) setFrameOriginY:(CGFloat)newY {
        CGRect f = self.frame;
        f.origin.y = newY;
        self.frame = f;
    }

@end

I could DRY up the methods using blocks... I'll do that at some point soon, I hope.

Yar
always good on category methods of frameworks you don't own to mark the methods with a unique prefix. In Google Toolbox for Mac we use gtm_ so this would be gtm_setFrameWidth: etc. That way if Apple decides in the future to define setFrameWidth: it doesn't conflict with your category.
dmaclach
Thanks @dmaclach, this all seems so primitive compared to Java, which of course doesn't let you modify framework classes at all :) I will take your advice.
Yar
@dmaclach, I have to say that while I did mark a best answer to this question, I still don't understand why you can't just do `self.frame.size.width = 30;'...
Yar