有两种方法可以解决这个问题:
1. 使用 Xcode 12.5.1 或更高版本
使用 Xcode 12.5.1 或更高版本构建应用程序,这似乎已修复与 10.14 之前系统的兼容性。
如果您希望仍然能够使用旧 Xcode 版本(即 Xcode 11 和更早版本)打开项目,则不能将新的 NSSearchToolbarItem 放入情节提要中,否则旧 Xcode 版本将拒绝打开它。
在这种情况下,您将继续使用NSToolbarItem
带有NSSearchField
控件的经典版本。NSSearchToolbarItem
挑战是在运行 macOS 11 或更高版本时将其替换为。
我尝试了几种方法,例如从工具栏中显式删除经典搜索工具栏项目,然后添加新的,并实现委托功能来提供它。虽然这样可行,但在让用户自定义工具栏时会引起麻烦:然后对话框将继续显示旧的搜索项和新的搜索项。解决这个问题的唯一方法是访问私有函数(_setAllowedItems
和_setDefaultItems
),但我对此并不满意。
我终于找到了这个相当的解决方案:
- 创建一个新的自定义类,我们将其命名为
SmartSearchToolbarItem
,并使其成为NSToolbarItem
.
- 在情节提要中,将 Search Field 的类从 更改
NSToolbarItem
为SmartSearchToolbarItem
。
- 将以下代码添加到
SmartSearchToolbarItem
实现中:
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101600
@interface NSSearchToolbarItem : NSObject
- (instancetype)initWithItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier;
@end
#endif
@implementation SmartSearchToolbarItem
-(instancetype)initWithItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier
{
self = [super initWithItemIdentifier:itemIdentifier]; // this is necessary even if we won't use it, or we'll crash in Big Sur
Class cls = NSClassFromString(@"NSSearchToolbarItem");
if (cls) {
self = (id) [[cls alloc] initWithItemIdentifier:itemIdentifier];
}
return self;
}
这不仅会自动将经典搜索项替换为 Big Sur 中的新搜索项,以后还会使用连接的 IBActions 和 IBOutlets,这是我不太了解的部分。因此,无需在代码中复制和属性。
修复分段控件
如果您的工具栏中碰巧有分段控件,那么您还需要此代码来调整它们的大小作为位置,因为它们在 Big Sur 与早期的 macOS 系统上具有不同的宽度(10.15 和 10.14 会很好,但如果你也支持 10.13,你肯定需要这个):
- (void)fixSegmentedToolbarItemWidths // call this from `viewWillAppear`
{
if (@available(macOS 10.14, *)) {
// no need to set the sizes here
} else {
BOOL didChange = NO;
for (NSToolbarItem *item in self.view.window.toolbar.items) {
NSControl *control = (NSControl*)item.view;
if ([control isKindOfClass:NSSegmentedControl.class]) {
[control sizeToFit];
NSRect frame = control.frame;
const int padding = 2;
item.minSize = NSMakeSize(frame.size.width+padding, item.minSize.height);
item.maxSize = item.minSize;
didChange = YES;
}
}
if (didChange) {
[self.view.window.toolbar validateVisibleItems];
}
}
}
示例代码
Github页面