You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Objective-C在Xcode中重定义Mac应用窗口参数及绘制像素

Hey Andrew, let's work through your macOS Objective-C window and drawing challenges step by step—since you're building a personal 3D FPS starting with macOS, getting these foundational pieces right will set you up nicely for later 2D/3D rendering work.


Fixing Custom Window Position & Size Issues

First, let's tackle why your frame modifications aren't sticking, plus that delegate outlet error.

1. Why modifying the window frame/frameOrigin isn't working

The most common culprit here is timing: if you're trying to adjust the window before it's fully initialized, your changes get overwritten by the MainMenu.xib's default settings. macOS also uses a bottom-left coordinate origin (unlike iOS's top-left), so double-check you're not placing the window off-screen by accident.

Here's the correct way to set a custom frame in your AppDelegate:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Grab the main window instance (ensure this is connected in your xib!)
    NSWindow *mainWindow = self.window;
    
    // Define your custom frame: x, y, width, height (bottom-left origin)
    NSRect customFrame = NSMakeRect(100, 100, 1280, 720);
    
    // Apply the frame with display:YES to force an immediate update
    [mainWindow setFrame:customFrame display:YES animate:NO];
    
    // If you just want to adjust the origin (keep the same size)
    // [mainWindow setFrameOrigin:NSMakePoint(200, 200)];
}

Make sure your AppDelegate has a window IBOutlet connected to the window in MainMenu.xib (check the Connections Inspector for the AppDelegate object).

2. Fixing the "Failed to connect (delegate) outlet" error

This happens because your MainMenu.xib has an invalid delegate connection from the NSWindowController to your AppDelegate—either the outlet doesn't exist in your code, or the connection was misassigned.

Here's how to fix it:

  1. Open MainMenu.xib, find the NSWindowController object in the Document Outline.
  2. Open the Connections Inspector (right panel, icon looks like a plug).
  3. Look for the delegate connection—if it's linked to AppDelegate, delete that connection.
  4. Instead, set the delegate via code to avoid xib misconfiguration:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MainMenu"];
    
    // Make sure your AppDelegate conforms to NSWindowDelegate in the .h file
    windowController.window.delegate = self;
    
    [windowController showWindow:nil];
    
    // Now set your custom frame on the window controller's window
    [windowController.window setFrame:NSMakeRect(100, 100, 1280, 720) display:YES animate:NO];
}

And update your AppDelegate.h to declare the protocol:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>

@property (strong, nonatomic) NSWindow *window;

@end

Drawing Points/Pixels in a macOS Window

For simple pixel drawing, the easiest approach is to create a custom NSView subclass and override its drawRect: method—this is the standard way to do custom rendering in macOS.

Step 1: Create a custom drawing view

Make a new NSView subclass (let's call it DrawingCanvas):

DrawingCanvas.h

#import <Cocoa/Cocoa.h>

@interface DrawingCanvas : NSView

@end

DrawingCanvas.m

#import "DrawingCanvas.h"

@implementation DrawingCanvas

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Get the Core Graphics context for drawing
    CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext];
    
    // Example 1: Draw a single red pixel at (50, 50)
    CGContextSetRGBFillColor(ctx, 1.0, 0.0, 0.0, 1.0); // RGBA: red, full opacity
    CGContextFillRect(ctx, NSMakeRect(50, 50, 1, 1)); // x, y, width, height
    
    // Example 2: Draw a 5x5 blue "point" at (100, 100)
    CGContextSetRGBFillColor(ctx, 0.0, 0.0, 1.0, 1.0);
    CGContextFillRect(ctx, NSMakeRect(100, 100, 5, 5));
}

@end

Note: In drawRect:, the coordinate system still uses the bottom-left origin, so (0,0) is the bottom-left corner of the view.

Step 2: Attach the custom view to your window

Update your AppDelegate to replace the default content view with your custom canvas:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Create the canvas with your desired size
    DrawingCanvas *canvas = [[DrawingCanvas alloc] initWithFrame:NSMakeRect(0, 0, 1280, 720)];
    
    // Set it as the window's content view
    [self.window setContentView:canvas];
    
    // Set your custom window position/size
    [self.window setFrame:NSMakeRect(100, 100, 1280, 720) display:YES animate:NO];
}

Dynamic updates

If you need to draw new points later (e.g., in response to user input), call [canvas setNeedsDisplay:YES]—this triggers drawRect: to run again, so you can update your drawing logic each time.


内容的提问来源于stack exchange,提问作者AndrewGreen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:23:10