0

I am trying to understand how NSLayoutAnchor works in Objective-C by converting a simple Swift app to it. The Swift app creates an NSView subclass which sets its layer's background color to a randomly generated color (with an extension to NSColor), then creates two instances of it in AppDelegate (inside application:didFinishLaunchingWithOptions), then creates the array of constraints, add the two views to the superview, activates the constraints and... that's it.
In my Objective-C version, where I have tried to convert everything, it seems that the two custom NSView subclass instances never get initialised. A step-by-step debugging shows their value to be = nil, and while the app launches, the console says:

-[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]

From that I deduced something may be wrong with the way I initialised my NSView subclass, but not even with duck-explaining I can find what may be wrong. This is the code in ColorView.m ("RandomColor.h") is the extension to get the randomColor method:

#import "ColorView.h"
#import "RandomColor.h"

@implementation ColorView

- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    
    if (self) {        
        self.wantsLayer = YES;
        self.layer = [[CALayer alloc] init];
        
        self.layer.backgroundColor = [[[NSColor alloc] randomColor] CGColor];
    }
    
    NSLog(@"Color View Initialized");
    return self;
}

@end

Here is the extension, if you want to test it, but that doesn't seem to be the problem:

@implementation NSColor (RandomColor)
- (NSColor *)randomColor {
    CGFloat r = drand48();
    CGFloat g = drand48();
    CGFloat b = drand48();
    CGFloat alpha = 1.0;
    
    return [NSColor colorWithRed:r green:g blue:b alpha:alpha];
}

@end

In AppDelegate.h I declared two ColorView properties called leftView and rightView, while in AppDelegate.m:

@synthesize leftView;
@synthesize rightView;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    leftView.translatesAutoresizingMaskIntoConstraints = NO;
    rightView.translatesAutoresizingMaskIntoConstraints = NO;
    
    NSView *view = [self.window contentView];
    [self.window setBackgroundColor:[NSColor systemMintColor]];
    
    if (view) {
        [view addSubview:leftView];
        [view addSubview:rightView];
        
        [NSLayoutConstraint activateConstraints:@[
            [leftView.topAnchor constraintEqualToAnchor:[view topAnchor]],
            [leftView.leftAnchor constraintEqualToAnchor:[view leftAnchor]],
            [leftView.rightAnchor constraintEqualToAnchor:[view centerXAnchor]],
            [leftView.widthAnchor constraintGreaterThanOrEqualToConstant:150],
            [leftView.heightAnchor constraintEqualToConstant:100],
            [rightView.centerXAnchor constraintEqualToAnchor:[view centerXAnchor] constant:50],
            [rightView.centerYAnchor constraintEqualToAnchor:[view centerYAnchor]],
            [rightView.widthAnchor constraintEqualToConstant:100],
            [rightView.heightAnchor constraintEqualToConstant:100]
        ]];
    }
}

I also looked at the archived documentation for NSView subclassing, stored here, but most of it was either not compiling or not helping in a meaningful way.
Could you please tell me where I am wrong in this code, or what am I missing? Please also correct me if the title is not appropriate for the question.
Thank you so much

2
  • Where are your ColorView instances being allocated and initialized? You need something like leftView=[[ColorView alloc]initWithFrame:someRect]; for them to actually exist. Commented Jun 18, 2022 at 15:36
  • Wow ... I had forgotten leftView = [[ColorView alloc] init]; and rightView = [[ColorView alloc] init]; ... such a beginner mistake. Ok ... could you please add this as an answer so that I can credit you at least for the inspirational suggestion? Commented Jun 18, 2022 at 15:37

1 Answer 1

1

In the sample code leftView and rightView are never allocated.

Adding leftView=[[ColorView alloc]initWithFrame:someRect]; (and similar for rightView) should make the code work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.