我正在设置OSX开发的第一步,我遇到了一些问题。我对iOS开发有很多经验,但OSX程序的窗口系统是另外的。
我正在建立一个像twitter这样的社交网络的客户端,需要2个单独的窗口控制器才能首次启动应用程序,如果您已登录以显示时间线,则需要一个,如果您尚未登录,则需要登录。在info.plist中,您需要为它提供一个main.xib。为此,我制作了一个我隐藏的空xib,第二个应用程序启动。这对IMO来说不是一个好的解决方案,对此有什么更好的解决方案?我想保持窗口与appdelegate分开,因为这样我可以保持我的代码分离。
这给我一个问题,当我打开我的“第二个”窗口进行登录时,它会显示但不活动。我已经尝试了所有的东西,例如orderFront:,activateIgnoringOtherApps:,makeKeyAndOrderFront:&更多。但这一切都行不通。
所以:首先,是否有更好的方法来处理info.plist中需要的main.xib,如果没有,是否有解决焦点问题的方法? 我正在使用osx 10.7
答案 0 :(得分:2)
对于多次一次性,你真的应该将你的app delegate与你的窗口控制器分开。继续,从模板中创建一个新的Cocoa应用程序。在MainMenu.xib
中,删除该窗口。在AppDelegate.h
中删除IBOutlet
到NSWindow
。创建一些NSWindowController
的新子类,其中包含XIB
s - 可能LoginWindowController
和TimelineWindowController
。
对于“最终”NSWindowController
子类(即那些不会被子类化的子类),指定初始化器的最佳实践是
//for our example class LoginWindowController
- (id)init
{
self = [super initWithWindowNibName:@"LoginWindowController"];
if (self) {
//....
}
return self;
}
现在,在您的app委托中,您应该为两个不同的窗口控制器实例@properties
:
//Within AppDelegate.m
#import "AppDelegate.h"
#import "LoginWindowController.h"
#import "TimelineWindowController.h"
@interface AppDelegate ()
@property (nonatomic) LoginWindowController *loginWindowController;
@property (nonatomic) TimelineWindowController *timelineWindowController;
//For the sake of this demo, add a property for the loggedIn state:
@property (nonatomic) BOOL loggedIn;
@end
您应该在app委托中使用某种方法来呈现正确的窗口控制器。我们称之为-updateWindowVisibility
:
- (void)updateWindowVisibility
{
BOOL isLoggedIn = self.loggedIn;
BOOL loginWindowVisible = self.loginWindowController.window.isVisible;
BOOL showLoginWindow = !isLoggedIn;
BOOL timelineWindowVisible = self.timelineWindowController.window.isVisible;
BOOL showTimelineWindow = isLoggedIn;
if (!loginWindowVisible && showLoginWindow) {
if (!self.loginWindowController) self.loginWindowController = [[LoginWindowController alloc] init];
[self.loginWindowController showWindow:nil];
} else if (loginWindowVisible && !showLoginWindow) {
[self.loginWindowController close];
self.loginWindowController = nil;
}
if (!timelineWindowVisible && showTimelineWindow) {
if (!self.timelineWindowController) self.timelineWindowController = [[TimelineWindowController alloc] init];
[self.timelineWindowController showWindow:nil];
} else if (timelineWindowVisible && !showTimelineWindow) {
[self.timelineWindowController close];
self.timelineWindowController = nil;
}
}
上面实现的这种方法比目前的设置需要更多的工作,但是当你需要显示/隐藏其他窗口时应该更容易修改。此时剩下要做的就是从-updateWindowVisibility
拨打-applicationDidFinishLaunching:
。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.isLoggedIn = NO;
[self updateWindowVisibility];
}
我发布了一个example app to github来演示这种方法。
答案 1 :(得分:1)
在结构方面(你的第一个问题),我建议这样做:
如果已登录,请执行以下操作:
NSViewController *loggedInController = [[NSViewController alloc] initWithNibName:@"NibNameGoesHere" bundle:nil];
[[self megaView] addSubview:[loggedInController view]];
否则使用您的loggedOutController进行上述过程:
NSViewController *loggedOutController = [[NSViewController alloc] initWithNibName:@"OtherNibNameGoesHere" bundle:nil];
[[self megaView] addSubview:[loggedOutController view]];
这应该可以让你得到你想要的东西,并且可能会在这个过程中清理你的第二个问题。我的答案与Nate的区别在于我的使用相同的窗口。有条件地实例化视图控制器并将其视图加载到超视图中可能是我学到的Cocoa最重要的方面。