这个问题最初是针对objective-c编程语言提出的。在撰写本文时,swift甚至还没有存在。
是否可以仅更改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 ANALOGY 自行承担风险
对于那些熟悉CSS
的人来说,这个想法非常类似于使用:
margin-left: 2px;
而不是必须改变整个值:
margin: 5px 5px 5px 2px;
答案 0 :(得分:95)
回答您的原始问题:是的,可以只更改CGRect
结构中的一个成员。此代码不会引发任何错误:
myRect.size.width = 50;
然而,不的可能性是更改CGRect
的单个成员,该成员本身是另一个对象的属性。在这种非常常见的情况下,您必须使用临时局部变量:
CGRect frameRect = self.frame;
frameRect.size.width = 50;
self.frame = frameRect;
原因是使用属性访问者self.frame = ...
等同于[self setFrame:...]
,此访问者始终需要整个CGRect
。在这种情况下,将C样式struct
访问与Objective-C属性点表示法混合使用效果不佳。
答案 1 :(得分:28)
我喜欢Ahmed Khalaf's answer,但我想到你也可以写出一些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);
获取发烧友(一年后更新我发布)
但它中有一个冗余的self.frame
。要解决此问题,您可以在category
上添加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;
}
享受。
答案 2 :(得分:6)
基于ArtOfWarfare's solution(非常棒),我构建了没有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;
}
答案 3 :(得分: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)
}
}
答案 4 :(得分:1)
根据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)
}
}
答案 5 :(得分: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),并假设我们只想替换宽度。
答案 6 :(得分:0)
setFrameX(x)
setFrameY(y)
setFrameWidth(width)
...
相反,在swift中,我们可以使用默认参数仅在一次调用中设置多个参数:
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)
答案 7 :(得分:-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;
}
它对我来说非常有用:)