Why Does Swift Provide Both a Cgrect Initializer and a Cgrectmake Function

Why does swift provide both a CGRect initializer and a CGRectMake function?

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.

What's the difference between using CGSizeMake and CGSize? Is one better than the other?

The CGSize constructor is a Swift extension on CGSize:

extension CGSize {
public static var zero: CGSize { get }
public init(width: Int, height: Int)
public init(width: Double, height: Double)
}

CGSizeMake is a leftover inline function bridged from Objective-C:

/*** Definitions of inline functions. ***/

// ...

public func CGSizeMake(width: CGFloat, _ height: CGFloat) -> CGSize

Both have the same functionality in Swift, the CGSize constructor is just more "Swifty" than the other and provided as a convenience.

Cannot invoke + with an argument of type CGRect error in Swift

The way @Martin R does works well, but later I found that there are no reasons to bother to use CGFloat() - you can just use CGRect() instead of CGRectMake() in Swift, on which you can specify the argument as Int as well as Double or CGFloat to all the x, y, width, and height properties as long as all the four properties are of the same type. Also, you cannot omit the name of each property which you can in the case of CGRectMake(), but this is easier, more flexible, and considered to be the default CGRect initializer in Swift.

Update CGRectMake to CGRect in Swift 3 Automatically

Apple actually does provide this feature. All you have to do is go to:

Edit > Convert > To Latest Swift Syntax...

Sample Image

And then follow the onscreen prompts.

This will solve your syntax issues and you won't have to make new functions for all of the various removed functions.

Swift numerics and CGFloat (CGPoint, CGRect, etc.)

I wrote a library that handles operator overloading to allow interaction between Int, CGFloat and Double.

https://github.com/seivan/ScalarArithmetic

As of Beta 5, here's a list of things that you currently can't do with vanilla Swift.
https://github.com/seivan/ScalarArithmetic#sample

I suggest running the test suite with and without ScalarArithmetic just to see what's going on.

CGGeometry Extension - Override CGRectMake

CGGeometry is not a class actually neither a struct, the file is called CGGeometry where the defenitions of geometric primitives are defined, so you cannot override it.

Swift Initialization - Why are multiple init functions being called?

super.init() calls self.init(frame:...). Essentially, it's just their way of saying that frame is optional; if you don't pass it, they assign a frame of (0,0,0,0).

func init() {
self.init(frame:CGRectMake(0,0,0,0));
}

Where to initialize in Swift?

So your options for initialisation in swift are numerous. With your current example you cannot use the method getFrame() yet because you do not yet have a reference to self as the ViewController has not get been initialised. Instead you could use:

let myView: UIView = UIView(frame: CGRectMake(0, 0, 100, 100))

As this does not require the reference to self. Alternatively you could lazy instantiation which will get run after self is available (this can only be used with var not let:

lazy var myView: UIView = {
return UIView(frame:self.getFrame())
}()

To answer your question, when using UIKit class where you often don't have control over their instantiation you can keep doing it the same was as you were in objective c and use implicitly unwrapped optionals (to prevent you having to use a ! or ? every time you instantiate a variable, e.g.:

var myView: UIView!

override func viewDidLoad(){
super.viewDidLoad();

myView = UIView(frame:getFrame())
}

This however does not work with let constants, as they need to be assigned either immediately or in the constructor of the object. Hope this helps.

What's this {{0,0},{w,h}} doing?

It's a standard C structure initialization construct. Any structure can be initialized at declaration time by providing its contents in order within curly braces like this. Because a CGRect contains a CGPoint and a CGSize, you use one set of braces for the CGRect, then another set for each of CGPoint & CGSize.

How to call Swift initializer methods with multiple param in Objective-C


To be accessible and usable in Objective-C, a Swift class must be a
descendant of an Objective-C class or it must be marked @objc.

And also this answer.

This apple doc will also help you understand.

So the options for you is to either inherit the class of yours from some Objective C class (In this case compiler adds @objc) or add @objc yourself to your class.

You also need to add to your Objective C class-

#import "<#ProjectName#>-Swift.h"

Real solution to this specific question

Please look at this question, you will get your solution yourself. :)

That question says that optional parameters can't be exposed from Swift to Objective C as all parmeters become _Nonnull.

So I think you will need to create another initializer without optionals and default parameters.



Related Topics



Leave a reply



Submit