如何用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.
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:
- Open MainMenu.xib, find the
NSWindowControllerobject in the Document Outline. - Open the Connections Inspector (right panel, icon looks like a plug).
- Look for the
delegateconnection—if it's linked to AppDelegate, delete that connection. - 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
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

