为什么NSFontManager.availableMembers(OffFontFamily:)在Xcode 8 GM中崩溃?

为什么NSFontManager.availableMembers(OffFontFamily:)在Xcode 8 GM中崩溃?,xcode,macos,crash,xcode8,nsfontmanager,Xcode,Macos,Crash,Xcode8,Nsfontmanager,我是在Xcode 8 Beta 6(8S201h)中写的: guard let faceMembers=NSFontManager.shared().availableMembers(ofFontFamily:familyName??fontName)else{return nil} 而且效果很好。现在我已经升级到Xcode 8 GM Seed(8A218a)Xcode 8(8A218a),它崩溃了(EXC\u BAD\u指令(code=EXC\u I386\u INVOP,subcode=0

我是在Xcode 8 Beta 6(8S201h)中写的:

guard let faceMembers=NSFontManager.shared().availableMembers(ofFontFamily:familyName??fontName)else{return nil}
而且效果很好。现在我已经升级到Xcode 8 GM Seed(8A218a)Xcode 8(8A218a),它崩溃了(
EXC\u BAD\u指令(code=EXC\u I386\u INVOP,subcode=0x0)

使用调试器缩小它的范围,我发现
NSFontManager.availableMembers(ofFontFamily:)
中的某些内容非常讨厌这个,因为无论我在其中放入什么,它都会崩溃,即使是像Helvetica Neue这样的常用字体(肯定安装了!)

(lldb)po NSFontManager.shared()
(lldb)po familyName
▿ 可选的
-一些:“Helvetica Neue”
(lldb)po fontName
“HelveticaNeue”
(lldb)po NSFontManager.shared().availableMembers(ofFontFamily:familyName??fontName)
错误:执行被中断,原因:EXC_BAD_指令(代码=EXC_I386_INVOP,子代码=0x0)。
进程已返回到表达式求值之前的状态。
(lldb)po NSFontManager.shared().availableMembers(ofFontFamily:familyName!)
错误:执行被中断,原因:EXC_BAD_指令(代码=EXC_I386_INVOP,子代码=0x0)。
进程已返回到表达式求值之前的状态。
(lldb)po NSFontManager.shared().availableMembers(ofFontFamily:“不是真正的字体?!”)
无
所以当我给它传递一个有效的字体族名称时,它崩溃了。。。但是当我传递一个假的时,它返回
nil

这是我可以解决的问题,还是Xcode 8 GM Seed Xcode 8的问题,将在SDK更新中解决?


在翻阅了坠机日志后,我发现了这种怀疑:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libswiftFoundation.dylib        0x0000000107cbb249 _TZFE10FoundationSa26_forceBridgeFromObjectiveCfTCSo7NSArray6resultRGSqGSax___T_ + 153
1   libswiftCore.dylib              0x00000001079031f3 swift_dynamicCast + 1635
2   libswiftCore.dylib              0x000000010790448b _dynamicCastFromExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*, swift::DynamicCastFlags) + 91
3   libswiftCore.dylib              0x0000000107903919 swift_dynamicCast + 3465
4   libswiftFoundation.dylib        0x0000000107d6a348 _TPA__TFFs15_arrayForceCastu0_rFGSax_GSaq__U_FQ_Q0_ + 56
5   libswiftFoundation.dylib        0x0000000107cbbc45 _TFEsPs10Collection3mapurfzFzWx8Iterator7Element_qd__GSaqd___ + 885
6   libswiftFoundation.dylib        0x0000000107cbb4c3 _TFs15_arrayForceCastu0_rFGSax_GSaq__ + 227
7   libswiftFoundation.dylib        0x0000000107cbb7a5 _TZFE10FoundationSa36_unconditionallyBridgeFromObjectiveCfGSqCSo7NSArray_GSax_ + 197
线程0崩溃::调度队列:com.apple.main-Thread
0 libswiftftfFoundation.dylib 0x0000000107cbb249\u tzfe10基金会从ObjectiveFTCSO7nsArray6结果Qgsax\uuuuuuuuuuuuuuuu+153建立的强制桥接
1 libswiftCore.dylib 0x00000001079031f3 swift_dynamicCast+1635
2 libswiftCore.dylib 0x000000010790448b_dynamicCastFromExistential(swift::OpaqueValue*,swift::OpaqueValue*,swift::TargetExistentialTypeMetadata const*,swift::TargetMetadata const*,swift::DynamicCastFlags)+91
3 libswiftCore.dylib 0x0000000107903919 swift\u dynamicCast+3465
4 libswiftffoundation.dylib 0x0000000107d6a348\U TPA\uuuuuuuuu TFFs15\U阵列forceCastu0\U rFGSax\U GSaq\uuuuuuuuuuu FQ\uuu+56
5 libswiftftfoundation.dylib 0x0000000107cbbc45\u tfesps10collection3mapurfzfwx8iterator7element\u qd\u\u GSaqd\u\u+885
6 libswiftffoundation.dylib 0x0000000107cbb4c3\u TFs15\u数组forcecastu0\u rFGSax\u GSaq\u+227
7 libswiftffoundation.dylib 0x0000000107cbb7a5\u TZFE10FoundationSa36\u无条件地从ObjectiveCfgsqcso7nsarray\u GSax+197跨越

因此,它似乎在Swift基金会内部崩溃,在一些名为
\u forceBridgeFromObjectiveC
的函数中。。。不确定这是否对任何人都有帮助,但它确实确认了它在SDK/运行时中。

在此期间,我唯一能解决这个问题的方法是在objective-c类中创建一个静态方法。然后,我将标题导入到桥接标题中,并从Swift 3调用静态方法,在那里它工作得很好

希望这能帮助你度过这些困难时期

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

@interface WorkAround : NSObject

+ (NSArray *)typefacesForFontFamily:(NSString *)family;

@end


#import "WorkAround.h"

@implementation WorkAround

/// Returns an array of arrays, or nil, that contain information about
/// each typeface found for the specified font family.
+ (NSArray *)typefacesForFontFamily:(nonnull NSString *)family {
  NSFontManager *fontManager = [NSFontManager sharedFontManager];
  return [fontManager availableMembersOfFontFamily:family];
}
@end
#导入
#进口
@接口解决方法:NSObject
+字体字体字体字体系列:(NSString*)字体系列;
@结束
#导入“WorkAround.h”
@实现变通方法
///返回一个数组或nil数组,其中包含有关
///为指定字体系列找到的每个字体。
+(NSArray*)字体字体字体系列:(非空NSString*)系列{
NSFontManager*fontManager=[NSFontManager-sharedFontManager];
返回[fontManager availableMembersOfFontFamily:family];
}
@结束

约瑟夫·E.的回答是一个很好的起点。然而,为了让它在Swift 3、Xcode 8(8A218a)中工作,我不得不采用不同的方法

  • 子类NSFontManager(在目标C中),如果还没有桥接头,则创建桥接头。
  • 确保将语言更改为(目标C)。很重要的一点是,你这样做,因为它看起来,即使有这样做的选择

  • 实施
  • FontManager.h

    #import <Cocoa/Cocoa.h>
    
    @interface FontManager : NSFontManager
        NS_ASSUME_NONNULL_BEGIN
    
        + (NSArray *)typefacesForFontFamily:(NSString *)family;
    
    
        NS_ASSUME_NONNULL_END
    @end
    
    桥接头.h

    //
    //  Use this file to import your target's public headers that you would like to expose to Swift.
    //
    
    #import "FontManager.h"
    
  • 在Swift 3项目中的使用

    if let fontMembers = FontManager.typefaces(forFontFamily: "Arial") as? [[Any]]  { }
    

  • 我将此作为Apple Bug
    28209297
    提交。我提交的Apple Bug被标记为仍然打开的
    28195947
    的副本。您为此提交了雷达吗?苹果漏洞管理是一场彻头彻尾的噩梦,我们永远不会知道结果。如果没有,我将提交one@livingstonef我是通过苹果雷达提交的,不是OpenRadar,如果这是你的意思的话。谢谢你的努力,但这对我来说仍然很失败:周,这是不同的。。。?很抱歉我就是说不出来。
    if let fontMembers = FontManager.typefaces(forFontFamily: "Arial") as? [[Any]]  { }