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...
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
App Crash on Sign in (Xcode 9.3) Exc_Bad_Access (Code=1, Address=0X1)
Wait Until an Asynchronous API Call Is Completed - Swift/Ios
With Firebase, Swift Removeobserver(Withhandle Does Not Remove the Observer
iOS Tabbar Item Title Issue in iOS13
Is It Possible in Swift to Add Variables to an Object at Runtime
Evaluate Bool Property of Optional Object in If Statement
Swift Programming Nserrorpointer Error etc
Round Top Corners of a Uiview in Swift
Swift Property Observer in Protocol Extension
Swift Realm, Load the Pre-Populated Database the Right Way
Add Custom Header to Collection View Swift
How to Change the Uinavigationbar Title's Position
What Is the "@Exported" Attribute in Swift
How to Resolve This Build Issue - Cannot Assign to Property: 'Date' Is a Get Only Property
Delete All Characters After a Certain Character from a String in Swift
Bounce Rays with Enumeratebodies Alongraystart
Render a 3D Model (Hair) with Semi-Transparent Texture in Scenekit