Failed to use CGPoint, the struct, in Swift

440 views Asked by At

My Situation:

I have learnt Swift for a while and Swift is my only language I've learnt for iOS Development, which means I did not learn Objective-C Systematically. I can just read OC Code a little.

I got a CGPoint problem when I tried to translate a OC project to Swift project.

Objective-C Code:

- (void)drawFramesetter:(CTFramesetterRef)framesetter
   attributedString:(NSAttributedString *)attributedString
          textRange:(CFRange)textRange
             inRect:(CGRect)rect
            context:(CGContextRef)c
{
           .
           .

CTFrameRef frame = CTFramesetterCreateFrame(framesetter, textRange, path, NULL);
CFArrayRef lines = CTFrameGetLines(frame);
NSInteger numberOfLines = CFArrayGetCount(lines);
CGPoint lineOrigins[numberOfLines];  // *** The place I had been obstructed! ***

           .
           .
           .
}

My Question:

  • I have no idea why this line of code, declared as CGPoint lineOrigins[numberOfLines], have no * to create an instance variable, lineOrigins ?

    My unproven guess is that CGPoint is a struct rather than a Class, but it's still so mysterious to me that created an instance variable without * and =.

  • Another point confused me is [numberOfLines]. Is [numberOfLine] an array?

  • Please teach me how to translate CGPoint lineOrigins[numberOfLines]; into Swift or show me some hints.


An big appreciation for your guide and time.

Ethan Joe

2

There are 2 answers

5
Duncan C On BEST ANSWER

The line

CGPoint lineOrigins[numberOfLines];

Creates a C array of CGPoint objects.

It's written inside a function, so it creates a local (stack) variable. That code will only compile if numberOfLines is a compile-time constant, because the compiler has to allocate a fixed amount of space for your array on the stack at compile time.

C structs are simple "templates" that interpret a block of memory as containing one or more scalar values. The values are stored sequentially in memory.

A C array is also a way of looking at a block of memory, as a sequential series of one or more scalar "things." Those scalar things can be simple scalars like integers, or they can be structs.

When you define a C array like in your example, the compiler makes memory space for the full array, and sets the variable to a pointer to the first element.

The type of lineOrigins is actually type "pointer to CGPoint". In C, an array type and a pointer to an object of that type are interchangeable. It is a bit like a Swift unsafe buffer pointer. There's no range checking.

EDIT:

A similar Swift declaration would be:

var lineOrigins = [CGPoint]()

or, to pre-fill it with a bunch of zero points:

var lineOrigins = [CGPoint](count: numberOfLines, repeatedValue: CGPointZero)
4
gnasher729 On

CGPoint is a C struct, which should translate into a C structure.

CGPoint lineOrigins [...] is a local variable named lineOrigins, which is an array of struct CGPoint.

CGPoint lineOrigins [numberOfLines] is a local variable named lineOrigins, which is an array of struct CGPoint with numberOfLines elements.

There is an array init method where you pass the number of array elements, and one array element which is duplicated.