Equivalent of CGFloat.maximum in Objective-C - objective-c

In Swift I can do this:
let z = CGFloat.maximum(20.0, 50.0) // z = 50.0
Tried to convert it to Objective-C:
CGFloat z = [CGFloat maximum:20.0, 50.0]; // Also tried (CGFloat *)
But getting a compilation error:
Receiver type 'CGFloat' (aka 'double') is not an Objective-C class
To simplify example I used 2 constants, but in reality function will receive 2 CGFloat variables, if it matters.
So how can I get maximum between 2 CGFloats in Objective-C?

CGFloat z = MAX(20, 50);
CGFloat is not an object, so there is no * and no methods.

Related

How can I deal with operation between Int and CGFloat?

In Objective-C I can do the following operation:
Objective-C code:
CGFloat width = CGRectGetWidth(mView.bounds);
CGFloat total = width*[myArray count];
but in Swift, it will raise an error:
Could not find an overload for '*' that accepts the supplied arguments
How can I avoid this situation elegantly?
First, let's create some demo data
let array: NSArray = ["a", "b", "c"] //you could use a Swift array, too
let view = UIView() //just some view
Now, everything else works almost the same way as in Obj-C
let width: CGFloat = CGRectGetWidth(view.bounds)
or simply
let width = CGRectGetWidth(rect) //type of the variable is inferred
and total:
let total = width * CGFloat(array.count)
Note that we have to add a CGFloat cast for array.count. Obj-C would implicitly cast NSUInteger to CGFloat but Swift has no implicit casts, so we have to add an explicit one.
In Swift you cannot multiply two numbers of different types (NSNumber, Int, Double, etc.) directly. The width of a CGRect is of floating point type and the array count is of integer type. Here's a working example:
let myArray: Int[] = [1,2,3]
let rect: CGRect = CGRect(x:0,y:0,width:100,height:100)
let total: Double = rect.size.width * Double(myArray.count)
Swift does not allow operations between two numbers of different types. Therefore, before to multiply your array.count (Int) by your width (CGFloat), you'll have to cast it to CGFloat.
Fortunately, Swift provides a simple CGFloat initializer init(_:) that creates a new CGFloat from an Int. This initializer has the following declaration:
init<Source>(_ value: Source) where Source : BinaryInteger
Creates a new value, rounded to the closest possible representation.
The Swift 5 Playground sample code below shows how to perform your calculation by using CGFloat's initializer:
import UIKit
import CoreGraphics
// Set array and view
let array = Array(1...3)
let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
let view = UIView(frame: rect)
// Perform operation
let width = view.bounds.width
let total = width * CGFloat(array.count)
print(total) // prints: 300.0
need to change All Int to CGFloat Type, or change All CGFloat to Int
let a: CGFloat = 0.25
let b: Int = 1
// wrong: Binary operator '*' cannot be applied to operands of type 'CGFloat' and 'Int'
// let c = a * b
// right: change All Int to CGFloat Type
let r = a * CGFloat(b)
// right: change All CGFloat to Int
let r = Int(a) * b

What is "CG_INLINE CGRect" definition in Objective C called?

What is the following structure called in Objective C,
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;
}
I want to create my own definition for making an object that would hold multiple parameters that I pass. Currently I am using a static method within a class that would take multiple parameters and return an object. But this syntax of CGRectMake is a perfect solution i could use. What is the structure actually called in Objective C syntax?
CGRectMake() is a function. Functions are a C language feature, not unique to Objective-C. Therefore, they don't have a special name in Objective-C. They're called C functions.
If you're asking about this seemingly cryptic syntax:
CG_INLINE CGRect
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
CG_INLINE is a special token that does nothing more than declare a function as inline. You can find a description of CG_INLINE in this question:
What does CG_INLINE do?
CGRect is the return type. The line break that follows is mere whitespace; it's a somewhat common code-formatting convention in C to break a line after the return type in a function definition.
CGRectMake is the function name.
The rest that follows is its argument list and function body.
If you want to create a function, you can place its definition in your .m file, with a corresponding forward declaration in the .h file.

Incompatible type 'double'

I'm assigning a CGFloat animatedDistance and I'm getting this error.
Here I'm assigning value to animatedDistance
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 140;
heightFraction is CGFloat as well.
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
What type should be animatedDistace? Can someone help me?
floor returns a double. On some platforms, CGFloat is a float. animatedDistance should be typed as a double (you can cast it to a CGFloat if needed).
Use this to get a vector... CGpoint vector = ccpSub(cgpoint 1, cgpoint 2);
And if you want double/float values then do this:
CGpoint.location
for whatever you are trying to find the coordinates of, then assign a float to CGPoint.location.y and another float to CGPoint.location.x
You need cocos2d for this by the way. I think.
Sounds to me like you declared animatedDistance as holding some kind of pointer, such as NSNumber *, or a structure, such as CGSize. Either way, you can't assign a CGFloat there.
If animatedDistance holds an NSNumber object, create one around the value. Back when you asked this question, the way to do this was [NSNumber numberWithDouble:floor(…)]. Now, you can just use #(floor(…)).
If animatedDistance holds a CGSize or other structure, you're going to have to decide for yourself how to meaningfully convert from the single number you have to the kind of structure you want.

Error: Incompatible types in assignment

I built a class and created a method which initialize all variables.
on .h
-(void) initWithX:(float *)x_ andY:(float *)y_ andWidth:(float *)width_;
and on .m
-(void) initWithX:(float *)x_ andY:(float *)y_ andWidth:(float *)width_{
[super init];
x = x_; ***
y = y_; ***
width = width_; ***
}
Lines with * give me error "Incompatible types in assignment" but I don't understand: I'm giving 3 floats as told in the .h!!!
Thank you all
Pass your floats by value by removing the *:
- (void)initWithX:(float)x_ andY:(float)y_ andWidth:(float)width_;
- (void)initWithX:(float)x_ andY:(float)y_ andWidth:(float)width_ {
[super init];
x = x_;
y = y_;
width = width_;
}
Otherwise the method is asking for pointers to floats (float *), and not their actual primitive values.
you are asking for float pointers and probably assigning them to float variables. take out the asterisks in the method declarations.

what do the square brackets next to an NSDecimal object mean?

Im using core-plot for my graphing component of my iPhone app, and I have been using NSDecimal object a lot.
One of the lines of their code that I have seen is like this:
-(void)plotPoint:(NSDecimal *)plotPoint forPlotAreaViewPoint:(CGPoint)point
{
NSDecimal x;
//do some calculations on x
plotPoint[CPCoordinateX] = x;
}
Where, CPCoordinateX is deinfed as below:
typedef enum _CPCoordinate {
CPCoordinateX = 0, ///< X axis
CPCoordinateY = 1, ///< Y axis
CPCoordinateZ = 2 ///< Z axis
} CPCoordinate;
The line:
plotPoint[CPCoordinateX] = x;
is what I dont understand, how can a NSDecimal be assigned to like this?
In my code, Im trying to call this method, like so:
NSDecimal dec = CPDecimalFromInteger(0);
[plotSpace plotPoint:&dec forPlotAreaViewPoint:point];
NSDecimalNumber *newx = [[NSDecimalNumber alloc] initWithDecimal:dec];
NSDecimal x = dec[CPCoordinateX];
//NSLog(#"converted at: %#", newx);
but Im getting compile errors:
error: subscripted value is neither array nor pointer
Can someone please explain this to me?
plotPoint is a pointer and pointers can be indexed like arrays using the subscript operator:
int array[] = { 1, 2, 3 };
NSLog(#"x=%d, y=%d, z=%d", array[0], array[1], array[2]);
// prints "x=1, y=2, z=3"
int *pointer = array; // implicit conversion to pointer
NSLog(#"x=%d, y=%d, z=%d", pointer[0], pointer[1], pointer[2]);
// also prints "x=1, y=2, z=3"
You can also use those expressions for assignments:
array[0] = 4;
pointer[1] = 5;
But you can only use the subscript operator on arrays or pointers:
NSDecimal dec = CPDecimalFromInteger(0);
dec[0]; // illegal, dec is a single NSDecimal value, not pointer or array
To actually pass a point -plotPoint:forPlotArrayViewPoint: you need a C-style array or a dynamic array of 2 or 3 NSDecimals (according to what dimensions the method expects), e.g.:
NSDecimal decPoint[] = {
CPDecimalFromInteger(0),
CPDecimalFromInteger(0),
CPDecimalFromInteger(0)
};
[plotSpace plotPoint:decPoint forPlotAreaViewPoint:point];
On that array you can now also use the subscript operator:
NSDecimal x = decPoint[CPCoordinateX];
It's a C array.