编写可在iOS和Mac OS应用程序中使用的类的好方法是什么?我不是想在这里获得完整的跨平台UI解决方案,只是在Mac上运行的支持应用程序中使用我的iPhone应用程序中的几个模型类.其中一些类需要一些小的改动才能在Mac OS下进行编译.这似乎是对宏的调用,但我不知道通常使用哪些宏.任何建议或分享经验将不胜感激.
我是NSButtonCell的子类,用于自定义绘图(可自定义的主题).我想自定义复选框和单选按钮的绘制方式.
有谁知道如何检测按钮是复选框还是单选按钮?
只有-setButtonType:,没有getter,-showsStateBy和-highlightsBy似乎都没有为复选框提供任何唯一的返回值,这些复选框也不适用于带有图像和备用图像的常规按钮.
到目前为止,我已经找到了两个(不是非常漂亮)的变通方法,但它们可能会被MAS拒绝应用程序:
使用[self valueForKey:@"buttonType"].这是有效的,但由于方法不在标题中,我认为这是Apple不希望我做的事情.
覆盖-setButtonType:和-initWithCoder:在手动设置或从XIB设置时跟踪按钮类型.这里的问题是XIB情况,因为用于将按钮类型保存到磁盘的密钥没有记录.所以,我再次使用私有API.
我真的希望这是NSButtonCell的直接替代品,而不是强制客户端代码使用单独的ULIThemeSwitchButtonCell类用于复选框,第三个用于单选按钮.
设置:
我开发了一个典型的基于 Cocoa Document的OS X应用程序.
我的目的是支持Apple的用户界面保留功能,以便从以前的应用程序运行中恢复打开的Documents/Windows.
我没有压倒任何相关的方法,例如:
-[NSWindow isRestorable]
-[NSResponder encodeRestorableStateWithCoder:]
-[NSResponder decodeRestorableStateWithCoder:]
-[NSApplication restoreWindowWithIdentifier:state:completionHandler:]
-[NSDocumentController restoreWindowWithIdentifier:state:completionHandler:]
Run Code Online (Sandbox Code Playgroud)
(注意:-[NSWindow isRestorable]在我的文档窗口中YES,默认情况下已经返回.大概这是基于文档的应用程序的一项功能)
在我的与UI Preservation相关的应用程序中,我认为我没有做任何与众不同的事情.
问题:
我的应用程序中的UI保留无效.但它以一种非常奇怪的方式失败了.当我运行我的应用程序时(通过在Xcode中构建和运行它或通过独立运行分发版本),Saved Application State正确创建普通文件夹并使用正确的应用程序状态信息填充.

如果我强制退出我的应用程序(通过突然停止正在运行的Xcode构建或通过Dock Force Quit菜单项),然后重新启动我的应用程序,UI保留功能完美地工作.该应用程序查找存储在Saved Application State文件夹中的信息,并从之前的运行中正确恢复打开的Documents/Windows.
但是,每当我正常退出我的应用程序时,整个Saved Application State文件夹都会被删除(我可以在Finder中看到这种情况).因此,下次启动应用程序时,没有要恢复的存储状态,并且恢复失败.
我跟踪了这个文件夹删除,直到-[NSApplication terminate:]调用后的某个时间发生.
所以我放了一个符号断点unlink(),当然,AppKit中的一些代码是故意删除Saved Application State文件夹及其所有内容.

请注意unlink()来自NSPersistentUI I/O主线程上调用的队列的调用 …
所以我习惯了iOS开发,所以我对NSFetchedResultsController非常满意.但是,这在Mac OS X环境中不存在.我知道我可以使用NSArrayController作为替代品.我可能正在使用这个类非常错误,但它一直工作到现在.我初始化NSArrayController如下:
NSArrayController* newConversationsController = [NSArrayController new];
newConversationsController.managedObjectContext = context;
newConversationsController.entityName = entityName;
newConversationsController.sortDescriptors = sortDescriptors;
newConversationsController.automaticallyRearrangesObjects = YES;
NSError* error = nil;
[newConversationsController fetchWithRequest:nil merge:NO error:&error];
NSCAssert(!error, error.description);
Run Code Online (Sandbox Code Playgroud)
然后我听取NSManagedObjectContext的更改并获取并重新加载NSTableView,如下所示:
[self.conversationsController fetchWithRequest:nil merge:YES error:&error];
NSAssert(!error, error.description);
[self.tableView reloadData];
Run Code Online (Sandbox Code Playgroud)
正如我之前提到的,我可能使用这个完全错误,但我不喜欢使用绑定.现在来看实际问题:应用程序的另一个类可能会删除NSArrayController持有的NSManagedObject.NSArrayController立即释放这个删除的对象,使我无法确定哪个对象.最终目标是知道什么索引被删除了哪个对象,这样我就可以为NSTableView的行设置动画.
我希望我的目标很明确.谢谢你的帮助
我正在将应用程序从iOS迁移到OSX,在OSX中是否有类似于UIActivityViewController的东西.对于像Facebook,Twitter,邮件,消息共享这样的东西,我需要做类似的事情;
NSArray *activityItems = [NSArray arrayWithObjects:shareString, shareImage, shareUrl, nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
activityViewController.excludedActivityTypes = @[UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll];
activityViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:activityViewController animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)
如何在OSX中实现这一目标?
当NSTextField的宽度发生变化时,如何让自动布局自动将NSTextField包装到多行?
我有许多NSTextFields在检查器窗格中显示静态文本(即:标签).当用户调整检查器窗格的大小时,如果需要,我希望右侧标签能够回流到多行.
(Finder的"获取信息"面板执行此操作.)
但是我无法弄清楚自动布局约束的正确组合以允许这种行为.在所有情况下,右侧的NSTextFields拒绝换行.(除非我明确添加允许它的高度约束.)
视图层次结构使得每个灰色条带是包含两个NSTextField的视图,左侧是属性名称,右侧是属性值.当用户调整检查器窗格的大小时,我希望属性值标签根据需要自动调整其高度.
现在的情况:

我希望发生什么:

(请注意,这种行为与我遇到的关于NSTextFields和自动布局的大多数Stack Overflow问题不同.这些问题希望文本字段在用户输入时增长.在这种情况下,文本是静态的,NSTextField配置为看起来像一个标签.)
更新1.0
考虑到@ hamstergene的建议,我将NSTextField子类化并制作了一个示例应用程序.在大多数情况下,它现在可以工作,但现在有一个小的布局问题,我怀疑这是因为NSTextField的框架与自动布局所期望的完全不同步.在下面的屏幕截图中,右侧标签都是垂直间隔的top约束.在调整窗口大小时,Where字段将正确调整大小并进行包装.但是,在Kind我再次调整窗口"一个像素"之前,文本字段不会被推下.
示例:如果我将窗口的大小调整为Where文本字段首次换行的正确宽度,那么我会在中间图像中得到结果.如果我再向窗口调整一个像素,则会Kind正确设置字段的垂直位置.
我怀疑这是因为自动布局正在通过,然后帧被明确设置.我想自动布局在那个传球上没有看到,但是在下一次传球时看到它,并相应地更新位置.
假设这是问题,我如何通知我正在进行的这些更改的自动布局,setFrameSize以便它可以再次运行布局.(而且,最重要的是,不要陷入layout-setFrameSize-layout-etc.的递归状态...)
解
我想出了一个解决方案,似乎与我希望的完全一致.取而代之的子类的NSTextField,我只是覆盖layout的superview的NSTextField问题.在内部layout,我设置preferredMaxLayoutWidth文本字段,然后触发布局传递.这似乎足以使它大部分工作,但它留下了布局短暂"错误"的恼人问题.(见上面的注释).
解决方案似乎是调用setNeedsDisplay然后一切正常工作.
- (void)layout {
NSTextField *textField = ...;
NSRect oldTextFieldFrame = textField.frame;
[textField setPreferredMaxLayoutWidth:NSWidth(self.bounds) - NSMinX(textField.frame) - 12.0];
[super layout];
NSRect newTextFieldFrame = textField.frame;
if (oldTextFieldFrame.size.height != newTextFieldFrame.size.height) {
[self setNeedsDisplay:YES];
}
}
Run Code Online (Sandbox Code Playgroud) AVPlayer有一个叫做的属性rate,用于控制播放速率.1.0是正常速度,而值2.0或5.0应分别以2x和5x回放.
每当我将播放速率值设置为高于1.0(比如说10.0)时,播放就会非常不稳定,并且看起来大量的帧会因为播放器无法跟上而丢失.
但是,QuickTime Player中的相同值(使用相同的电影)可以生成平滑的播放速率2x, 5x, 10x, 30x and 60x(由QuickTime播放器报告).
我创建了一个测试OS X应用程序,它只包含一个AVPlayerView和两个用于设置播放速率的按钮.1.0工作速度如预期的那样,但10.0产生的速度非常不稳定.
然而,AVPlayerView有一个奇怪的怪癖,如果你鼠标点击播放时间线寻找到另一个位置(当它以10x和波动的方式播放时),那么AVPlayerView将"修复"播放并且电影将以10x平稳播放.只需单击播放时间线即可.
有谁知道如何平稳播放1x以外的费率?这显然不是硬件问题或文件大小问题,因为QuickTime Player和AVPlayerView都可以做到这一点.
尝试
这个问题表明它可能是一个音频问题(事实上,QuickTime播放器和AVPlayerView在转发时都会使音频静音)但是我所有试图禁用所有音轨,静音所有音轨或改变音频音调算法的尝试似乎都没有做出改变.即使没有音频,播放仍然不稳定.
我也试过停止播放然后prerollAtRate:completionHandler用新的速率呼叫,但这也没有什么区别.
QuickTime Player和AVPlayerView正在做什么,可以以10倍,30倍甚至60倍的速度播放流畅的电影?
Apple的Accessibility Inspector工具显示与当前检查的UI元素对应的Objective-C类.请参NSButtonCell见此屏幕截图的最底部:
但是,如何在我自己的代码中提取此信息?Apple七年之久的UIElementInspector示例代码中的辅助功能方法不会显示元素的类名.
对Accessibility Inspector进行反向工程,暗示可以通过AXClassName属性获取Objective-C类名,但该属性对我来说总是零.
我有一个带有 a 的 macOS 应用程序,NavigationView并希望在窗口的工具栏中拥有默认的 ToggleSidebar 项。
目前我将 ToolbarItem 的目标设置toolbarWillAddItem(_)为NSToolbarDelegate.
在我实现的 AppDelegate 内部
@objc func toggleSidebar(_ sender: Any) {
((window.contentView?.subviews.first?.subviews.first?.subviews.first as? NSSplitView)?.delegate as? NSSplitViewController)?.toggleSidebar(self)
}
Run Code Online (Sandbox Code Playgroud)
此解决方案现在正在运行。如果 SwiftUI 的实现将改变这一点。
那么如何才能以更好的方式做到这一点呢?
我正在为 macOS 制作一个 SwiftUI 应用程序,我想通过检测用户手指的位置将触控板用作 (x, y) 输入。我想能够检测到的多个手指搁在触控板上(不拖移)。我怎么做?
以前有人问过类似的问题,但我再次问,因为那是近 10 年前的问题,答案都在 Obj-C 中(Swift 3 中的一个),我想知道是否有更新的方法。最重要的是,我不知道如何将 Obj-C 代码实现到我的 SwiftUI 应用程序中,所以如果没有任何更新的方法,如果有人能解释如何实现旧的 Obj-C 代码,我将不胜感激。
为了说明我的意思,AudioSwift 应用程序的这个视频演示正是我想要的。macOS 本身也用这个来手写中文(虽然我不需要识别字符)。
appkit ×10
macos ×7
cocoa ×6
objective-c ×3
swift ×2
swiftui ×2
uikit ×2
autolayout ×1
avfoundation ×1
avplayer ×1
core-data ×1
ios ×1
iphone ×1
nsbutton ×1
nstableview ×1
xcode ×1