- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在关注 Handmade Hero 项目,Casey Muratori 在该项目中从头开始创建了一个完整的游戏引擎,而不使用库。该引擎具有高度可移植性,因为它呈现自己的位图,然后平台特定的代码将其绘制到屏幕上。
在 Windows 下,通常有一个主应用程序循环,您可以在其中放置应重复执行的代码,直到应用程序终止。然而Cocoa中没有这样的东西。一旦 [NSApp run];
被调用,int main()
就变得毫无用处,你必须将代码放入委托(delegate)方法中才能执行。但这不是我想要的方式。我在网上找到了一些代码,其中有人已经完全按照我的要求做了,但代码有一些缺陷,或者可以说我只是不知道如何处理它。
#import <Cocoa/Cocoa.h>
#import <CoreGraphics/CoreGraphics.h>
#include <stdint.h>
#define internal static
#define local_persist static
#define global_variable static
typedef uint8_t uint8;
global_variable bool running = false;
global_variable void *BitmapMemory;
global_variable int BitmapWidth = 1024;
global_variable int BitmapHeight = 768;
global_variable int BytesPerPixel = 4;
global_variable int XOffset = 0;
global_variable int YOffset = 0;
@class View;
@class AppDelegate;
@class WindowDelegate;
global_variable AppDelegate *appDelegate;
global_variable NSWindow *window;
global_variable View *view;
global_variable WindowDelegate *windowDelegate;
@interface AppDelegate: NSObject <NSApplicationDelegate> {
}
@end
@implementation AppDelegate
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
// Cocoa will kill your app on the spot if you don't stop it
// So if you want to do anything beyond your main loop then include this method.
running = false;
return NSTerminateCancel;
}
@end
@interface WindowDelegate : NSObject <NSWindowDelegate> {
}
@end
@implementation WindowDelegate
- (BOOL)windowShouldClose:(id)sender {
running = false;
return YES;
}
-(void)windowWillClose:(NSNotification *)notification {
if (running) {
running = false;
[NSApp terminate:self];
}
}
@end
@interface View : NSView <NSWindowDelegate> {
@public
CGContextRef backBuffer_;
}
- (instancetype)initWithFrame:(NSRect)frameRect;
- (void)drawRect:(NSRect)dirtyRect;
@end
@implementation View
// Initialize
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (BitmapWidth * 4);
bitmapByteCount = (bitmapBytesPerRow * BitmapHeight);
BitmapMemory = mmap(0,
bitmapByteCount,
PROT_WRITE |
PROT_READ,
MAP_ANON |
MAP_PRIVATE,
-1,
0);
//CMProfileRef prof;
//CMGetSystemProfile(&prof);
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
backBuffer_ = CGBitmapContextCreate(BitmapMemory, BitmapWidth, BitmapHeight, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
//CMCloseProfile(prof);
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
CGContextRef gctx = [[NSGraphicsContext currentContext] graphicsPort];
CGRect myBoundingBox;
myBoundingBox = CGRectMake(0, 0, 1024, 768);
//RenderWeirdGradient(XOffset, YOffset);
CGImageRef backImage = CGBitmapContextCreateImage(backBuffer_);
CGContextDrawImage(gctx, myBoundingBox, backImage);
CGImageRelease(backImage);
}
internal void RenderWeirdGradient(int BlueOffset, int GreenOffset) {
int Width = BitmapWidth;
int Height = BitmapHeight;
int Pitch = Width*BytesPerPixel;
uint8 *Row = (uint8 *)BitmapMemory;
for(int Y = 0;
Y < BitmapHeight;
++Y)
{
uint8 *Pixel = (uint8 *)Row;
for(int X = 0;
X < BitmapWidth;
++X)
{
*Pixel = 0;
++Pixel;
*Pixel = (uint8)Y + XOffset;
++Pixel;
*Pixel = (uint8)X + YOffset;
++Pixel;
*Pixel = 255;
++Pixel;
}
Row += Pitch;
}
}
@end
static void createWindow() {
NSUInteger windowStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask;
NSRect screenRect = [[NSScreen mainScreen] frame];
NSRect viewRect = NSMakeRect(0, 0, 1024, 768);
NSRect windowRect = NSMakeRect(NSMidX(screenRect) - NSMidX(viewRect),
NSMidY(screenRect) - NSMidY(viewRect),
viewRect.size.width,
viewRect.size.height);
window = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
id menubar = [[NSMenu new] autorelease];
id appMenuItem = [[NSMenuItem new] autorelease];
[menubar addItem:appMenuItem];
[NSApp setMainMenu:menubar];
// Then we add the quit item to the menu. Fortunately the action is simple since terminate: is
// already implemented in NSApplication and the NSApplication is always in the responder chain.
id appMenu = [[NSMenu new] autorelease];
id appName = [[NSProcessInfo processInfo] processName];
id quitTitle = [@"Quit " stringByAppendingString:appName];
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle
action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
NSWindowController * windowController = [[NSWindowController alloc] initWithWindow:window];
[windowController autorelease];
//View
view = [[[View alloc] initWithFrame:viewRect] autorelease];
[window setContentView:view];
//Window Delegate
windowDelegate = [[WindowDelegate alloc] init];
[window setDelegate:windowDelegate];
[window setAcceptsMouseMovedEvents:YES];
[window setDelegate:view];
// Set app title
[window setTitle:appName];
// Add fullscreen button
[window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
[window makeKeyAndOrderFront:nil];
}
void initApp() {
[NSApplication sharedApplication];
appDelegate = [[AppDelegate alloc] init];
[NSApp setDelegate:appDelegate];
running = true;
[NSApp finishLaunching];
}
void frame() {
@autoreleasepool {
NSEvent* ev;
do {
ev = [NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: nil
inMode: NSDefaultRunLoopMode
dequeue: YES];
if (ev) {
// handle events here
[NSApp sendEvent: ev];
}
} while (ev);
}
}
int main(int argc, const char * argv[]) {
initApp();
createWindow();
while (running) {
frame();
RenderWeirdGradient(XOffset, YOffset);
[view setNeedsDisplay:YES];
XOffset++;
YOffset++;
}
return (0);
}
这是应用程序到目前为止需要运行的所有代码。只需将其复制并粘贴到空的 Xcode 命令行项目中即可运行。
但是,当您在应用程序运行时检查硬件时,您会发现 CPU 几乎以 100% 的速度运行。我读到这个问题的原因是由于自定义运行循环,应用程序必须一直搜索新事件。
此外,由于循环不会将控制权移交给委托(delegate)对象,因此 - (BOOL)windowShouldClose:(id)sender
等方法不再起作用。
问题:
是否有一种更好的方法来实现具有以下样式的自定义主应用程序循环,并且不会像我正在使用的那样浪费 CPU 时间?
同时(运行){//做东西}
由于应用程序委托(delegate)和窗口委托(delegate)方法不再响应,如何通过按窗口的关闭按钮来终止应用程序?
我现在花了几个小时在网上搜索 Cocoa 中的自定义主运行循环,但刚刚遇到了多线程和对我没有帮助的东西。
您能推荐一些对我的情况有帮助的在线资源/书籍吗?我真的很想获得一些处理不寻常事物(例如自定义运行循环)的资源。
最佳答案
我知道这已经晚了两年,但我在 Cocoa With Love 上发现了一篇文章,您可能会觉得有用。
https://www.cocoawithlove.com/2009/01/demystifying-nsapplication-by.html
我尝试以这种方式实现主事件循环,查看了 CPU 使用情况,它比我之前得到的更合理。我不完全知道为什么,但我会对此做更多研究。
关于objective-c - cocoa 中的自定义主应用程序循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38768645/
我正在通过 labrepl 工作,我看到了一些遵循此模式的代码: ;; Pattern (apply #(apply f %&) coll) ;; Concrete example user=> (a
我从未向应用商店提交过应用,但我会在不久的将来提交。 到目前为止,我对为 iPhone 而非 iPad 进行设计感到很自在。 我了解,通过将通用PAID 应用放到应用商店,客户只需支付一次就可以同时使
我有一个应用程序,它使用不同的 Facebook 应用程序(2 个不同的 AppID)在 Facebook 上发布并显示它是“通过 iPhone”/“通过 iPad”。 当 Facebook 应用程序
我有一个要求,我们必须通过将网站源文件保存在本地 iOS 应用程序中来在 iOS 应用程序 Webview 中运行网站。 Angular 需要服务器来运行应用程序,但由于我们将文件保存在本地,我们无法
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
假设我有一个安装在用户设备上的 Android 应用程序 A,我的应用程序有一个 AppWidget,我们可以让其他 Android 开发人员在其中以每次安装成本为基础发布他们的应用程序推广广告。因此
Secrets of the JavaScript Ninja中有一个例子它提供了以下代码来绕过 JavaScript 的 Math.min() 函数,该函数需要一个可变长度列表。 Example:
当我分别将数组和对象传递给 function.apply() 时,我得到 NaN 的 o/p,但是当我传递对象和数组时,我得到一个数字。为什么会发生这种情况? 由于数组也被视为对象,为什么我无法使用它
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章ASP转换格林威治时间函数DateDiff()应用由作者收集整理,如果你
我正在将列表传递给 map并且想要返回一个带有合并名称的 data.frame 对象。 例如: library(tidyverse) library(broom) mtcars %>% spl
我有一个非常基本的问题,但我不知道如何实现它:我有一个返回数据框,其中每个工具的返回值是按行排列的: tmp<-as.data.frame(t(data.frame(a=rnorm(250,0,1)
我正在使用我的 FB 应用创建群组并邀请用户加入我的应用群组,第一次一切正常。当我尝试创建另一个组时,出现以下错误: {"(OAuthException - #4009) (#4009) 在有更多用户
我们正在开发一款类似于“会说话的本”应用程序的 child 应用程序。它包含大量用于交互式动画的 JPEG 图像序列。 问题是动画在 iPad Air 上播放正常,但在 iPad 2 上播放缓慢或滞后
我关注 clojure 一段时间了,它的一些功能非常令人兴奋(持久数据结构、函数式方法、不可变状态)。然而,由于我仍在学习,我想了解如何在实际场景中应用,证明其好处,然后演化并应用于更复杂的问题。即,
我开发了一个仅使用挪威语的应用程序。该应用程序不使用本地化,因为它应该仅以一种语言(挪威语)显示。但是,我已在 Info.plist 文件中将“本地化 native 开发区域”设置为“no”。我还使用
读完 Anthony's response 后上a style-related parser question ,我试图说服自己编写单体解析器仍然可以相当紧凑。 所以而不是 reference ::
multicore 库中是否有类似 sapply 的东西?还是我必须 unlist(mclapply(..)) 才能实现这一点? 如果它不存在:推理是什么? 提前致谢,如果这是一个愚蠢的问题,我们深表
我喜欢在窗口中弹出结果,以便更容易查看和查找(例如,它们不会随着控制台继续滚动而丢失)。一种方法是使用 sink() 和 file.show()。例如: y <- rnorm(100); x <- r
我有一个如下所示的 spring mvc Controller @RequestMapping(value="/new", method=RequestMethod.POST) public Stri
我正在阅读 StructureMap关于依赖注入(inject),首先有两部分初始化映射,具体类类型的接口(interface),另一部分只是实例化(请求实例)。 第一部分需要配置和设置,这是在 Bo
我是一名优秀的程序员,十分优秀!