46

この質問は、もともとObjective-cプログラミング言語について尋ねられました。これを書いている時点では、swiftはまだ存在していませんでした。

質問

の1つのプロパティのみを変更することは可能CGRectですか?

例えば:

self.frame.size.width = 50;

それ以外の

self.frame = CGRectMake(self.frame.origin.x, 
                        self.frame.origin.y, 
                        self.frame.size.width, 
                        50);

もちろん、それself.frame.size.width読み取り専用であることを理解しているので、これをどのように行うのか疑問に思っていますか?

CSSアナロジー は自己責任で進めてください

に精通している方は、次CSSの方法を使用するのと非常によく似ています。

margin-left: 2px;

値全体を変更する代わりに:

margin: 5px 5px 5px 2px;
4

9 に答える 9

105

元の質問に答えるには:はい、CGRect構造体の1つのメンバーだけを変更することは可能です。このコードはエラーをスローしません:

myRect.size.width = 50;

ただし、それ自体が別のオブジェクトのプロパティであるaの単一のメンバーを変更することはできません。CGRectその非常に一般的なケースでは、一時的なローカル変数を使用する必要があります。

CGRect frameRect = self.frame;
frameRect.size.width = 50;
self.frame = frameRect;

この理由は、プロパティアクセサを使用することself.frame = ...はと同等で[self setFrame:...]あり、このアクセサは常に全体を期待するためCGRectです。この場合、CスタイルのstructアクセスとObjective-Cプロパティのドット表記を混在させることはできません。

于 2012-03-02T17:26:46.230 に答える
28

Ahmed Khalafの答えが好きでしたが、いくつかのC関数を書き出すだけでもよいことに気づきました...主な利点は、間違って使用している場合にエラーを追跡しやすくなることです。タイプ。

そうは言っても、私はこれらの関数宣言を含む.hファイルを作成しました。

CGRect CGRectSetWidth(CGRect rect, CGFloat width);
CGRect CGRectSetHeight(CGRect rect, CGFloat height);
CGRect CGRectSetSize(CGRect rect, CGSize size);
CGRect CGRectSetX(CGRect rect, CGFloat x);
CGRect CGRectSetY(CGRect rect, CGFloat y);
CGRect CGRectSetOrigin(CGRect rect, CGPoint origin);

そして、これらの関数の実装を持つ対応する.mファイル:

CGRect CGRectSetWidth(CGRect rect, CGFloat width) {
    return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height);
}

CGRect CGRectSetHeight(CGRect rect, CGFloat height) {
    return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height);
}

CGRect CGRectSetSize(CGRect rect, CGSize size) {
    return CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height);
}

CGRect CGRectSetX(CGRect rect, CGFloat x) {
    return CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height);
}

CGRect CGRectSetY(CGRect rect, CGFloat y) {
    return CGRectMake(rect.origin.x, y, rect.size.width, rect.size.height);
}

CGRect CGRectSetOrigin(CGRect rect, CGPoint origin) {
    return CGRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
}

だから、今、あなたがやりたいことをするために、あなたはただすることができます:

self.frame = CGRectSetWidth(self.frame, 50);

さらにファンシーになりましょう(1年後に更新しました)

ただし、これには冗長性self.frameがあります。これを修正するには、次のようなメソッドを使用してcategoryonを追加できます。UIView

- (void) setFrameWidth:(CGFloat)width {
    self.frame = CGRectSetWidth(self.frame, width); // You could also use a full CGRectMake() function here, if you'd rather.
}

そして今、あなたはただタイプすることができます:

[self setFrameWidth:50];

または、さらに良い:

self.frameWidth = 50;

そして、ちょうどあなたがこのようなことをすることができるように:

self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;

あなたはまたあなたのカテゴリーにこれを持っている必要があるでしょう:

- (CGFloat) frameWidth {
    return self.frame.size.width;
}

楽しみ。

于 2013-01-02T03:56:31.183 に答える
6

ArtOfWarfareのソリューション(これは本当に素晴らしいです)に基づいて、C関数なしでカテゴリを作成しましたUIView

使用例:

[self setFrameWidth:50];
self.frameWidth = 50;
self.frameWidth += 50;
self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;

ヘッダーファイルUIView+easy_frame.h

@interface UIView (easy_frame)

- (void) setFrameWidth:(CGFloat)width;
- (void) setFrameHeight:(CGFloat)height;
- (void) setFrameX:(CGFloat)x;
- (void) setFrameY:(CGFloat)y;

- (CGFloat) frameWidth;
- (CGFloat) frameHeight;
- (CGFloat) frameX;
- (CGFloat) frameY;

実装ファイルUIView+easy_frame.m

#import "UIView+easy_frame.h"
@implementation UIView (easy_frame)

# pragma mark - Setters

- (void) setFrameWidth:(CGFloat)width
{
  self.frame = CGRectMake(self.frame.origin.x,
                          self.frame.origin.y,
                          width,
                          self.frame.size.height);
}

- (void) setFrameHeight:(CGFloat)height
{
  self.frame = CGRectMake(self.frame.origin.x,
                          self.frame.origin.y,
                          self.frame.size.width,
                          height);
}

- (void) setFrameX:(CGFloat)x
{
  self.frame = CGRectMake(x,
                          self.frame.origin.y,
                          self.frame.size.width,
                          self.frame.size.height);
}

- (void) setFrameY:(CGFloat)y
{
  self.frame = CGRectMake(self.frame.origin.x,
                          y,
                          self.frame.size.width,
                          self.frame.size.height);
}

# pragma mark - Getters

- (CGFloat) frameWidth
{
  return self.frame.size.width;
}

- (CGFloat) frameHeight
{
  return self.frame.size.height;
}

- (CGFloat) frameX
{
  return self.frame.origin.x;
}

- (CGFloat) frameY
{
  return self.frame.origin.y;
}
于 2014-09-05T10:36:56.610 に答える
4

この種の個々のコンポーネントの変更を行う必要がある場合は、すべてのコードからアクセスできる場所に次のようなマクロを配置することをお勧めします。

#define CGRectSetWidth(rect, w)    CGRectMake(rect.origin.x, rect.origin.y, w, rect.size.height)
#define ViewSetWidth(view, w)   view.frame = CGRectSetWidth(view.frame, w)

このように、幅だけを変更する必要があるときはいつでも-あなたは単に書くでしょう

ViewSetWidth(self, 50);

それ以外の

self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, 50);
于 2012-09-19T00:45:10.437 に答える
2

n0_quarterの回答に基づいて、Swiftで記述されたUIView拡張機能は次のとおりです。

/**
*  Convenience category for manipulating UIView frames
*/
extension UIView {

    //MARK: - Getters
    func frameX() -> CGFloat {
        return frame.origin.x
    }

    func frameY() -> CGFloat {
        return frame.origin.y
    }

    func frameWidth() -> CGFloat {
        return frame.size.width
    }

    func frameHeight() -> CGFloat {
        return frame.size.height
    }

    //MARK: - Setters
    func setFrameX(x: CGFloat) {
        frame = CGRect(x: x, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
    }

    func setFrameY(y: CGFloat) {
        frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: frame.size.height)
    }

    func setFrameWidth(width: CGFloat) {
        frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: frame.size.height)
    }

    func setFrameHeight(height: CGFloat) {
        frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: height)
    }
}
于 2014-09-16T20:28:30.613 に答える
2

Swiftでは、アプリのUIViewクラスを拡張して、たとえば、次のようにテーブルヘッダービューを10ポイント上に移動できます。

    tableView.tableHeaderView!.frameAdj(0, -20, 0, 0)

(もちろん、AutoLayoutを使用している場合、実際には何も実行されない可能性があります... :))

UIViewを拡張する(アプリ内のすべてのUIViewとそのサブクラスに影響を与える)

extension UIView {
    func frameAdj(x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) {
            self.frame = CGRectMake(
                self.frame.origin.x + x,
                self.frame.origin.y + y,
                self.frame.size.width  + width,
                self.frame.size.height + height)
    }
}
于 2015-02-13T17:14:01.700 に答える
0

私がパーティーに遅刻しないことを願っています。これがObjCでの私の解決策です。

私にとっては、複数の関数ではなく単一の関数に固執することを好み、ポスターに示されているCSSアプローチが好きです。以下は、UIViewカテゴリに追加する関数です。

- (void)resetFrame:(CGRect)frame {
CGRect selfFrame = self.frame;
selfFrame.origin = CGPointMake(frame.origin.x>0 ? frame.origin.x : selfFrame.origin.x, frame.origin.y>0 ? frame.origin.y : selfFrame.origin.y);
selfFrame.size = CGSizeMake(frame.size.width>0 ? frame.size.width : selfFrame.size.width, frame.size.height>0 ? frame.size.height : selfFrame.size.height);
[self setFrame:selfFrame]; }

例に示されているように、提供されたCGRectの各値を調べ、値が0より大きい場合は、その値を置き換えたいことを意味します。したがって、CGRect(0,0,100,0)を実行でき、幅のみを置き換えたいと想定されます。

于 2015-11-20T04:11:20.063 に答える
0

次のように、頻繁にsetFrameメソッドを呼び出すのはあまり良くありません。 setFrameX(x) setFrameY(y) setFrameWidth(width) ...

代わりに、Swiftでは、デフォルトのパラメーターを使用して、1回の呼び出しでのみ複数のパラメーターを設定できます。

func setFrame(x x: CGFloat = CGFloat.NaN, y: CGFloat = CGFloat.NaN, width: CGFloat = CGFloat.NaN, height: CGFloat = CGFloat.NaN) {
    let newX = x.isNaN ? self.frame.origin.x : x
    let newY = y.isNaN ? self.frame.origin.y : y
    let newWidth = width.isNaN ? self.bounds.size.width : width
    let newHeight = height.isNaN ? self.bounds.size.height : height

    self.frame = CGRect(x: newX, y: newY, width: newWidth, height: newHeight)
}

次に、フレームのパラメータを更新する必要があります。

setFrame(x: x, width: min(maxX - x, titleLabel.bounds.size.width))
setFrame(width: titleDescriptionLabel.bounds.size.width + 5, height: titleDescriptionLabel.bounds.size.height + 6)
于 2015-12-10T07:37:37.520 に答える
-1
-(void) sizeScreen : (UIView *) size : (double) width : (double) height : (double) x : (double) y {
CGRect frameRect = size.frame;
frameRect.size.width = width;
frameRect.size.height = height;
frameRect.origin.x = x;
frameRect.origin.y = y;
self.view.frame = frameRect;

}

その仕事は私にとって素晴らしいです:)

于 2018-09-03T08:56:50.137 に答える