Help with NSGradient initWithColorsAndLocations:

I am attempting to use NSGradient’s method initWithColorsAndLocations:. The declaration and parameter descriptions seem simple enough:

- (instancetype)initWithColorsAndLocations:(NSColor *)firstColor, …;

A comma-separated list of alternating NSColor objects and location arguments (specified as CGFloat values). The first value after firstColor must be a location. Each location value must be between 0.0 and 1.0. The list must be nil-terminated.

Given that the method requires a comma-separated list, I used the following to define the gradient:

set theGradient to current application’s NSGradient’s alloc’s initWithColorsAndLocations_(NSColor’s blackColor(), 0.0, NSColor’s whiteColor(), 1.0, current application’s NSNull’s |null|())

In addition to ending the list with an instance of NSNull, I tried (missing value).
Unfortunately, this did not produce a gradient. No errors were reported by Script Debugger, but no gradient was created.

I speculated that either the way I used an underscore-parentheses was incorrect, or that nil required at the end of the list, was tripping me up.

Moving right along, I attempted to use an different method for creating the same type of gradient, its declaration and parameter descriptions are:

- (instancetype)initWithColors:(NSArray<NSColor *> *)colorArray
atLocations:(const CGFloat *)locations
colorSpace:(NSColorSpace *)colorSpace;
An array of NSColor objects representing the colors in the gradient.
An array of CGFloat values containing the location for each color in the gradient. Each value must be in the range 0.0 to 1.0. There must be the same number of locations as are colors in the colorArray parameter.
The color space to use for the gradient.

I anticipated using this would be easy because it did not require either a list for input nor a trailing nil. I defined the gradient as follows:

set colorArray to current application’s NSArray’s alloc’s initWithArray:{NSColor’s blackColor(), NSColor’s whiteColor()}
set locationArray to current application’s NSArray’s alloc’s initWithArray:{0.0, 1.0}
set theColorSpace to (NSColorSpace’s deviceRGBColorSpace())
set theGradient to current application’s NSGradient’s alloc’s initWithColors:colorArray atLocations:locationArray colorSpace:theColorSpace

Much to my dismay, this causes Script Debugger and Script Editor to crash.

I would appreciate any assistance anyone can offer.
Thank you.

You’re basically out of luck. The first method should work, but doesn’t because of a bug. The second method requires a pointer to a C array as an argument, which ASObjC can’t provide. No good news, I’m afraid.

Thank you, Shane.

While working on this, I noticed in the second method’s declaration, the input for the location parameter is specified as “(const CGFloat *)”. I did not know what that was; a quick Google search didn’t help. Is that what tells us that a pointer to a C array is required?

Despite the bug in the first method, I’m happy I had the syntax correct - which I learned about in your book!



Yes. A CGFloat is basically a C double, and the trailing asterisk is saying to pass a pointer to the first one in a C array.