Why does swift provide both a CGRect initializer a

2020-03-01 11:10发布

问题:

When I was learning about Core Graphics in swift, the tutorials that I watched on youtube use the CGRectMake function instead of the initializer of CGRect to create a CGRect instance.

This is so weird to me. I don't understand why should I use the former because the parameters are the same and I think there is no performance benefit to using the XXXMake function.

Also, why does swift even have such a "Make" function, when CGRect already has an initializer with exactly the same parameters? I think the developers of the modules is using a certain design pattern that I don't know. Did they use one? If yes, what is it? I really want to know some more design patterns.

回答1:

Short answer: CGRectMake is not "provided by Swift". The corresponding C function in the CoreGraphics framework is automatically imported and therefore available in Swift.

Longer answer: CGRectMake is defined in "CGGeometry.h" from the CoreGraphics framework as

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

In (Objective-)C, that function provides a convenient way to initialize a CGRect variable:

CGRect r = CGRectMake(x, y, h, w);

The Swift compiler automatically imports all functions from the Foundation header files (if they are Swift-compatible), so this is imported as

public func CGRectMake(x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect

You can either use that one, or one of the Swift initializers

public init(origin: CGPoint, size: CGSize)
public init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)
public init(x: Double, y: Double, width: Double, height: Double)
public init(x: Int, y: Int, width: Int, height: Int)

I don't think that it makes any performance difference. Many people might use CGRectMake() because they are used to it from the old pre-Swift times. The Swift initializers are more "swifty" and more expressive with the explicit argument labels:

let rect = CGRect(x: x, y: x, width: w, height: h)

Update: As of Swift 3/Xcode 8, CGRectMake is no longer available in Swift.