小编Wie*_*nke的帖子

有关NSApp的ModalForWindow,NSAlert的ModalForWindow和ModalSession的提示

我花了相当多的实验来澄清对Objective-C的"ModalForWindow"语言的一些混淆,以及随后如何使用模态会话.也许以下提示可以节省一些时间:

(如果您不熟悉这个概念:当一个窗口,通常是一个面板,运行模态时,它会阻止应用程序的其他部分响应,直到它被解除.)

"ModalForWindow"在不同的情况下意味着不同的东西.如果您使用loadNibNamed显示由xib定义的面板并且您希望它运行modal,请在显示后调用它:

// Make panelReviewImports modal, so that no other part of app will respond.
[[NSApplication sharedApplication] runModalForWindow:self.panelReviewImports];
Run Code Online (Sandbox Code Playgroud)

并在其解雇方法中采取以下措施:

[[NSApplication sharedApplication] stopModal];
Run Code Online (Sandbox Code Playgroud)

但对于NSAlert,beginSheetModalForWindow中的"窗口"指的是警报将作为工作表附加到的窗口,该窗口将被冻结,直到警报被解除.但该应用程序不会被冻结; 所有其他窗户将保持可操作性.如果您要附加警告如纸和 明确冻结的应用程序的其余部分,按照beginSheet代码用一个简单的调用runModal并使用返回代码,如下所示:

[alert beginSheetModalForWindow:self.window 
                  modalDelegate:self didEndSelector:@selector(abandonmentAlertDidEnd:returnCode:contextInfo:) 
                    contextInfo:nil];
NSInteger returnCode = [alert runModal];
[self abandonmentAlertDidEnd:alert returnCode:returnCode contextInfo:nil];
Run Code Online (Sandbox Code Playgroud)

(当然,您将实现了abandonmentAlertDidEnd:returnCode:contextInfo:代码作为类方法.)

或者,如果您希望警报作为居中面板运行,请自行调用runModal.

假设您要运行面板模式,如果用户提交无效条目,则后跟警报.在显示警报之前,您必须先停止模式 - 之后,由于某种原因,另一次调用runModalForWindow无法正常工作.对于此场景,您需要一个模态会话:

1)将NSModalSession属性添加到控制器类,因为modalSession必须可以跨多个方法访问.

2)显示面板后,调用beginModalSessionForWindow来实例化modalSession:

self.modalSession = [[NSApplication sharedApplication] beginModalSessionForWindow:self.panelForInput];
Run Code Online (Sandbox Code Playgroud)

3)使用调用runModalSession的while循环进行跟进,当它的返回值不等于NSRunContinuesResponse时断开:

while ([[NSApplication sharedApplication] runModalSession:self.modalSession] == NSRunContinuesResponse)
    continue;
Run Code Online (Sandbox Code Playgroud)

循环将中断,当用户点击其中一个面板按钮时,应用程序将释放.(在面板的文本字段中输入将使模态会话保持不变.)

4)在按钮处理中,如果用户的条目无效,则使用runModal调用警报.

5)紧接警报调用之后,在解除警报后将执行的代码中,您将上面使用的相同的while循环置于其中.小组的模态会话重新开始.

6)在关闭面板的处理中,无论是在有效输入还是取消时,都会调用endModalSession,奇怪的是,这是不够的; 你也必须调用stopModal,即使你从未调用runModalForWindow.

[[NSApplication sharedApplication] endModalSession:self.modalSession];
[[NSApplication sharedApplication] stopModal];
[self.panelForInput close];
Run Code Online (Sandbox Code Playgroud)

modal-dialog objective-c nsalert nspanel

29
推荐指数
1
解决办法
6858
查看次数

如何将滚动事件传递给父NSScrollView

我需要一个更大的滚动窗口内的固定大小的NSTextViews.IB要求textviews位于他们自己的NSScrollViews中,即使他们的最小/最大大小是固定的,以便它们实际上不会滚动.当在textview框架内制作触控板手势时(无论它们是否具有焦点),它们都会被textview的scrollview捕获,因此没有任何反应.

如何告诉textviews的scrollview将滚动事件传递到窗口的主滚动视图?(或许我应该问我如何告诉窗口的主滚动视图本身处理这些事件,而不是将它们传递给它的子滚动视图.)

IB结构是这样的:

  • 窗口
    • 窗口的内容视图
      • 窗口的大滚动视图(滚动事件的期望目标)
          • 单独的xib中的可交换内容视图
            • 用于textview的scrollview
              • 的TextView
并且,是的,当文本视图没有焦点时,窗口会正确滚动.

cocoa nsevent nsscrollview

7
推荐指数
3
解决办法
3723
查看次数

哪个更好,NSSet的containsObject或快速枚举?

我需要确定一个对象是否包含在Core Data to-many关系(这是一个NSSet)中,并且我试图决定哪两个解决方案更好:

解决方案1)

if ([managedObject.items containsObject:itemOfInterest])
    return …
Run Code Online (Sandbox Code Playgroud)

解决方案2)

for (NSManagedObject *item in managedObject.items)
    if ([item == itemOfInterest])
        return …
Run Code Online (Sandbox Code Playgroud)

解决方案1更简洁,但NSSet Class Ref表示快速枚举的性能优于NSSet的objectEnumerator.它是否也比containsObject更好?

core-data objective-c nsset

5
推荐指数
2
解决办法
4886
查看次数

为什么iOS类不采用copyWithZone协议来鼓励活动的mem mgt?

在与Cocoa合作之后最近转向iOS,我惊讶地得到一个带有以下错误的SIGABRT:" - [UIDeviceRGBColor copyWithZone:]:无法识别的选择器发送到实例..."我在UIColor上调用了"copy".

我查看了类引用,并且,zits,UIColor不采用任何协议,与NSColor相反.

现在,这不是什么大问题.我只是试图通过主动拥有一个颜色实例来提高效率,以便在使用后立即丢弃它.但我认为Apple在iOS中省略垃圾收集器背后的目的是鼓励开发人员完全按照我的目的去做,以便在内存不足,电池挑战的便携式设备上保持精简内存配置文件.

有关Apple理由的任何想法,还是我的假设中有一些错误?

memory-management objective-c copywithzone ios

5
推荐指数
1
解决办法
1965
查看次数

bytesWritten,但其他设备从不接收NSStreamEventHasBytesAvailable事件

我在iPhone和Mac之间建立了一个Bonjour网络.

用户在Mac中呈现的表格中选择iPhone的网络服务,并在两侧创建并打开一对流.

iPhone首先向Mac发送代码(整数).Mac成功收到它.

暂停用户输入和处理后,Mac会启动向iPhone发送代码:

NSInteger bytesWritten = [self.streamOut write:buffer maxLength:sizeof(uint8_t)];
// bytesWritten is 1.
Run Code Online (Sandbox Code Playgroud)

但iPhone永远不会获得NSStreamEventHasBytesAvailable事件.我在此之前仔细检查了一下,iPhone的NSInputStream上的streamStatus是2,它应该是NSStreamStatusOpen.

什么想法可能是错的?


更新:我运行了一个测试,其中Mac是第一个向iPhone发送整数的测试.再一次,我从Mac的输出流中获得了1的bytesWritten,但iPhone从未得到过NSStreamEventHasBytesAvailable事件.

所以iPhone的输入流肯定有问题.但我仔细检查:

  • iPhone的self.streamIn在h文件中正确输入为NSInputStream
  • iPhone接收2个NSStreamEventOpenCompleted事件,并检查流arg的类.一个是KindOfClass:[NSOutputStream类],另一个不是.
  • iPhone永远不会收到NSStreamEventEndEncountered,NSStreamEventErrorOccurred或NSStreamEventNone.
  • 如上所述,在Mac写入输出流之后,iPhone的输入流状态为2,即NSStreamStatusOpen.

这是用于创建iPhone输入流的代码.它使用CF类型,因为它是在C风格的套接字回调函数中完成的:

CFReadStreamRef readStream = NULL;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketNativeHandle, &readStream, NULL);
if (readStream) {
    CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
    server.streamIn = (NSInputStream *)readStream;
    server.streamIn.delegate = server;
    [server.streamIn scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                               forMode:NSDefaultRunLoopMode];
    if ([server.streamIn streamStatus] == NSStreamStatusNotOpen)
        [server.streamIn open];
    CFRelease(readStream);
}
Run Code Online (Sandbox Code Playgroud)

Update2:响应alastair评论的信息:

套接字选项

retain,release和copyDescription回调设置为NULL.optionFlags设置为acceptCallback.

套接字创建

这是用于在iPhone和Mac上设置套接字的方法,完成了我的评论尝试,以找出此代码中实际发生的事情,该代码改编自各种教程和实验(有效):

/**
 Socket creation, port assignment, socket scheduled in run loop.
 The socket represents the port on this app's …
Run Code Online (Sandbox Code Playgroud)

cocoa bonjour nsstream ios

5
推荐指数
1
解决办法
1963
查看次数

可以为NSTextField设置对齐或字体,但不能同时设置两者

我有一个面板笔尖,其中一个文本字段的出口,在笔尖中设置为居中对齐.当我显示面板时,我希望这个文本字段是粗体.由于NSTextField是NSControl的子类,因此它可以使用setAttributedStringValue方法并获取属性字符串.所以我加入了这样的粗体字体:

NSFont *fontBolded = [NSFont fontWithName:@"Baskerville Bold" size:12.0f];
NSDictionary *dictBoldAttr = [NSDictionary dictionaryWithObject:fontBolded forKey:NSFontAttributeName];   
NSString *sHelloUser = NSLocalizedString(@"Hello User", @"Hello User");
NSAttributedString *attrsHelloUser = [[NSAttributedString alloc] initWithString: sHelloUser attributes:dictBoldAttr];
[self.fooController.tfPanelCenteredField setAttributedStringValue:attrsHelloUser];  
[attrsHelloUser release];
Run Code Online (Sandbox Code Playgroud)

粗体显示OK,但现在该字段左对齐.

我尝试添加setAlignment,但它没有效果:

[self.fooController.tfPanelCenteredField setAlignment:NSCenterTextAlignment];
Run Code Online (Sandbox Code Playgroud)

所以我尝试将一个居中的parapraph样式添加到属性字符串的属性中:

NSFont *fontBolded = [NSFont fontWithName:@"Baskerville Bold" size:12.0f];
NSMutableParagraphStyle *paragStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];   
[paragStyle setAlignment:NSCenterTextAlignment]; 
NSDictionary *dictBoldAttr = [NSDictionary dictionaryWithObjectsAndKeys:paragStyle, NSParagraphStyleAttributeName, fontBolded, NSFontNameAttribute, nil];
NSString *sHelloUser = NSLocalizedString(@"Hello User", @"Hello User");
NSAttributedString *attrsHelloUser = [[NSAttributedString alloc] initWithString: sHelloUser attributes:dictBoldAttr];
[self.fooController.tfPanelCenteredField setAttributedStringValue:attrsHelloUser];  
[attrsHelloUser …
Run Code Online (Sandbox Code Playgroud)

cocoa nstextfield nsattributedstring

3
推荐指数
1
解决办法
3778
查看次数