3

我在 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_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0))。

使用调试器缩小范围,我发现里面的东西NSFontManager.availableMembers(ofFontFamily:)真的很讨厌这个,因为无论我放什么它都会崩溃,即使是像 Helvetica Neue 这样的常见(肯定安装!)字体。

(lldb) po NSFontManager.shared()
<NSFontManager: 0x6100000a24c0>

(lldb) po familyName
▿ Optional<String>
  - some : "Helvetica Neue"


(lldb) po fontName
"HelveticaNeue"


(lldb) po NSFontManager.shared().availableMembers(ofFontFamily: familyName ?? fontName)
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been returned to the state before expression evaluation.
(lldb) po NSFontManager.shared().availableMembers(ofFontFamily: familyName!)
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been returned to the state before expression evaluation.
(lldb) po NSFontManager.shared().availableMembers(ofFontFamily: "Not a real font?!")
nil

所以当我传递一个有效的字体系列名称时,它会崩溃......但是当我传递一个假字体时,它会返回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

因此,它似乎在 Swift-Foundation 中崩溃,在某个名为_forceBridgeFromObjectiveC...

4

2 回答 2

2

与此同时,我能弄清楚如何解决这个问题的唯一方法是在 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
于 2016-09-14T20:13:58.400 回答
1

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

  1. 子类 NSFontManager(在 Objective C 中),如果您还没有桥接头,请创建桥接头。 在此处输入图像描述 在此处输入图像描述

确保将语言更改为(目标 C)。这样做很重要,因为您似乎无法直接创建目标 cm 文件?,即使可以选择这样做。

  1. 执行

字体管理器.h

#import <Cocoa/Cocoa.h>

@interface FontManager : NSFontManager
    NS_ASSUME_NONNULL_BEGIN

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


    NS_ASSUME_NONNULL_END
@end

字体管理器.m

#import "FontManager.h"

@implementation FontManager
    NS_ASSUME_NONNULL_BEGIN

    + (NSArray *)typefacesForFontFamily:(nonnull NSString *)family {
        NSFontManager *fontManager = [self sharedFontManager];
        return [fontManager availableMembersOfFontFamily: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"
  1. 在你的 Swift 3 项目中使用

    if let fontMembers = FontManager.typefaces(forFontFamily: "Arial") as? [[Any]]  { }
    
于 2016-09-18T08:37:49.843 回答