CGPathRef与CGMutablePathRef

时间:2012-02-17 00:55:31

标签: ios cocoa-touch core-graphics

在iOS中,有两个C结构,表示描述可绘制形状的路径:CGPathRef和CGMutablePathRef。从它们的名称来看,似乎CGPathRef引用一旦创建的路径无法更改,而CGMutablePathRef引用可修改的路径。然而,事实证明,CGPathRef可以传递给一个期望CGMutablePathRef的函数,在我看来唯一的区别是前者在传递函数时会生成警告来修改路径,而后者不会吨。例如,以下程序:

#import <UIKit/UIKit.h>

@interface TestView : UIView {
    CGPathRef immutablePath;
    CGMutablePathRef mutablePath;
}
@end
@implementation TestView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        mutablePath = CGPathCreateMutable();
        immutablePath = CGPathCreateCopy(mutablePath); // actually you might just do "immutablePath = CGPathCreateMutable();" here - The compiler doesn't even complain

        self.backgroundColor = [UIColor whiteColor];
    }

    return self;
}


- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesBegan executed!");
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextAddPath(context, immutablePath);
    CGPathAddRect(immutablePath, NULL, CGRectMake(100.0, 100.0, 200.0, 200.0)); // generates a warning specified later
    CGContextFillPath(context);
}


@end


@interface TestViewController : UIViewController
@end

@implementation TestViewController

@end

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

@implementation AppDelegate

@synthesize window = _window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];

    // Instantiate view controller:
    TestViewController *vc = [[TestViewController alloc] init];
    vc.view = [[TestView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];
    return YES;
}
@end


int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, @"AppDelegate");
    }
}

这是编译器发出的警告: 将'CGPathRef'(又名'const struct CGPath *')传递给'CGMutablePathRef'类型的参数(又名'struct CGPath *')会丢弃限定符

也许我在这里忽略了这一点,但除了提醒程序员可能他并不打算修改被引用的路径(通过CGPathRef)进行修改之外,这两者之间还有其他区别吗?

1 个答案:

答案 0 :(得分:3)

在C中可以将错误的类型传递给函数,但它几乎总是不是一个好主意。即使从技术上讲它们似乎也被定义为相同的东西,但苹果可能有很好的理由将它们作为单独的东西。最有可能的是让更多代码可读和易懂,或者Apple计划稍后进行更改。

毕竟,跳转到定义会发现真正的差异:

typedef struct CGPath *CGMutablePathRef;
typedef const struct CGPath *CGPathRef;

CGPathRef是一个const typedef(如果你不确定这是什么的话,请谷歌吧)。但是,C允许您破坏const定义,这就是为什么您仍然可以将CGPathRef传递给期望CGMutablePathRef的函数并修改它的原因。它还解释了为什么它会抛出discards qualifiers警告。