2012-10-01 86 views
1

我測試使用自定義UIFont的應用程序。這種字體用在可縮放的UILabel中 - 它有一個CATiledLayer圖層。自定義UIFont呈現導致應用程序崩潰iOS 6

這是UILabel類的代碼:

#import "ZoomableLabel.h" 

@implementation ZoomableLabel 

+ (Class)layerClass 
{ 
    return [CATiledLayer class]; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     [self setupView]; 
    } 
    return self; 
} 

//- (id)initWithCoder:(NSCoder *)aDecoder { 
// self = [super initWithCoder:aDecoder]; 
// if (self) { 
//  // Initialization code 
//  [self setupView]; 
// } 
// return self; 
//} 

-(void)awakeFromNib { 
    [super awakeFromNib]; 
    [self setupView]; 
} 

- (void)setupView { 
    CATiledLayer *layerForView = (CATiledLayer *)self.layer; 
    layerForView.levelsOfDetailBias = 3; 
    layerForView.levelsOfDetail = 1; 
} 

-(void)setText:(NSString *)value { 
    self.layer.contents = nil; 
    [super setText:value]; 
    [self setNeedsDisplay]; 
} 

-(void)setTextColor:(UIColor *)value { 
    self.layer.contents = nil; 
    [super setTextColor:value]; 
    [self setNeedsDisplay]; 
} 

@end 

當運行的裝置或首次模擬器(上的應用程序是應用程序被安裝用於在第一時間在該設備上或模擬器)我碰到了。那麼這次崩潰不會再發生!更新:崩潰發生非常隨機(特別是當演示應用程序...),但不僅是第一次。這是我設法從XCode獲得的所有信息:

Thread 3 name: Dispatch queue: com.apple.root.default-priority 
Thread 3 Crashed: 0 WebCore       0x333adbfa WTF::HashTable<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> >::rehash(int) + 42 
1 WebCore       0x333adcd4 WTF::HashTableAddResult<WTF::HashTableIterator<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> > > WTF::HashTable<WebCore::FontData const*, std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*>, WTF::PairFirstExtractor<std::__1::pair<WebCore::FontData const*, WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*>, WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::HashTraits<WebCore::FontData const*> >::add<WTF::HashMapTranslator<WTF::HashMapValueTraits<WTF::HashTraits<WebCore::FontData const*>, WTF::HashTraits<WebCore::GlyphPageTreeNode*> >, WTF::PtrHash<WebCore::FontData const*> >, WebCore::FontData const*, WebCore::GlyphPageTreeNode*>(WebCore::FontData const* const&, WebCore::GlyphPageTreeNode* const&) + 56 
2 WebCore       0x333a5cac WebCore::GlyphPageTreeNode::getChild(WebCore::FontData const*, unsigned int) + 264 
3 WebCore       0x333a55d8 WebCore::Font::glyphDataAndPageForCharacter(int, bool, WebCore::FontDataVariant) const + 528 
4 WebCore       0x333a53b6 WebCore::Font::glyphDataForCharacter(int, bool, WebCore::FontDataVariant) const + 18 
5 WebCore       0x333a4b36 WebCore::WidthIterator::advance(int, WebCore::GlyphBuffer*) + 398 
6 WebCore       0x333a4794 WebCore::Font::floatWidthForSimpleText(WebCore::TextRun const&, WebCore::GlyphBuffer*, WTF::HashSet<WebCore::SimpleFontData const*, WTF::PtrHash<WebCore::SimpleFontData const*>, WTF::HashTraits<WebCore::SimpleFontData const*> >*, WebCore::GlyphOverflow*) const + 60 
7 WebCore       0x333a4546 WebCore::Font::width(WebCore::TextRun const&, WTF::HashSet<WebCore::SimpleFontData const*, WTF::PtrHash<WebCore::SimpleFontData const*>, WTF::HashTraits<WebCore::SimpleFontData const*> >*, WebCore::GlyphOverflow*) const + 250 
8 WebCore       0x333a60e0 WebCore::truncateString(WTF::String const&, float, WebCore::Font const&, unsigned int (*)(WTF::String const&, unsigned int, unsigned int, unsigned short*, bool), bool, float*, bool, float, bool) + 296 
9 WebCore       0x333a5fac WebCore::StringTruncator::rightTruncate(WTF::String const&, float, WebCore::Font const&, WebCore::StringTruncator::EnableRoundingHacksOrNot, float&, bool, float) + 60 
10 WebKit       0x375fc718 applyEllipsisStyle(WTF::String const&, WebEllipsisStyle, float, WebCore::Font const&, WebCore::StringTruncator::EnableRoundingHacksOrNot, float*, bool, float, bool) + 464 
11 WebKit       0x375ff3a8 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:drawUnderline:] + 5036 
12 WebKit       0x375fdfe8 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:renderedStringOut:] + 112 
13 WebKit       0x375fdf64 -[NSString(WebStringDrawing) __web_drawInRect:withFont:ellipsis:alignment:letterSpacing:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 108 
14 WebKit       0x375fdee4 -[NSString(WebStringDrawing) _web_drawInRect:withFont:ellipsis:alignment:lineSpacing:includeEmoji:truncationRect:measureOnly:] + 108 
15 WebKit       0x375fde64 -[NSString(WebStringDrawing) _web_sizeInRect:withFont:ellipsis:lineSpacing:] + 80 
16 UIKit       0x353698c2 -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:lineSpacing:] + 122 
17 UIKit       0x3535daa6 -[UILabel _legacy_drawTextInRect:baselineCalculationOnly:] + 594 
18 UIKit       0x35321c5a -[UILabel _drawTextInRect:baselineCalculationOnly:] + 162 
19 UIKit       0x35320a26 -[UILabel drawTextInRect:] + 446 
20 UIKit       0x35320860 -[UILabel drawRect:] + 68 
21 UIKit       0x3531fd20 -[UIView(CALayerDelegate) drawLayer:inContext:] + 360 
22 QuartzCore      0x37b84bb8 -[CALayer drawInContext:] + 108 
23 QuartzCore      0x37c62624 tiled_layer_render(_CAImageProvider*, unsigned int, unsigned int, unsigned int, unsigned int, void*) + 1416 
24 QuartzCore      0x37bd755c CAImageProviderThread(unsigned int*, bool) + 508 
25 libdispatch.dylib    0x37b5e95c _dispatch_root_queue_drain + 248 
26 libdispatch.dylib    0x37b5eabc _dispatch_worker_thread2 + 80 
27 libsystem_c.dylib    0x38862a0e _pthread_wqthread + 358 
28 libsystem_c.dylib    0x388628a0 start_wqthread + 4 

有沒有人對此有任何意見?我覺得這個崩潰不會在iOS 5設備上發生......

+0

有沒有人遇到這種情況?我該怎麼辦?向Apple報告錯誤?什麼? – Summon

+0

我想我看到了這個相同的錯誤。我沒有機會徹底調查它。我希望別人已經找到了解決方法。 – mahboudz

+0

我只在模擬器上遇到這個崩潰。至今。 – mahboudz

回答

1

這些都是基於CATiledLayer一個可縮放的標籤,從來沒有崩潰的h和.M類:

頁眉:

#import <QuartzCore/QuartzCore.h> 

@interface ZoomableLabel : UILabel { 
    CGPoint textDrawPoint; 
    CGPoint shadowDrawPoint; 
} 

@end 

實施:

#import "ZoomableLabel.h" 

@implementation ZoomableLabel 

+ (Class)layerClass 
{ 
    return [CATiledLayer class]; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     [self setupView]; 
    } 
    return self; 
} 

-(void)awakeFromNib { 
    [super awakeFromNib]; 
    [self setupView]; 
} 

- (void)setupView { 
    CATiledLayer *layerForView = (CATiledLayer *)self.layer; 
    layerForView.levelsOfDetailBias = 3; 
    layerForView.levelsOfDetail = 1; 
    textDrawPoint = CGPointMake(11, -22); 
    shadowDrawPoint = CGPointMake(10, -23); 
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 
     textDrawPoint = CGPointMake(11, -42); 
     shadowDrawPoint = CGPointMake(8, -46); 
    } 
} 

// DO NOT USER THESE METHODS ANYMORE 
//-(void)setText:(NSString *)value { 
//// self.layer.contents = nil; 
// [super setText:value]; 
// [self setNeedsDisplayInRect:self.bounds]; 
//} 
// 
//-(void)setTextColor:(UIColor *)value { 
//// self.layer.contents = nil; 
// [super setTextColor:value]; 
// [self setNeedsDisplayInRect:self.bounds]; 
//} 

// LEAVE IT EMPTY 
-(void)drawRect:(CGRect)r 
{ 
    // UIView uses the existence of -drawRect: to determine if should allow its CALayer 
    // to be invalidated, which would then lead to the layer creating a backing store and 
    // -drawLayer:inContext: being called. 
    // By implementing an empty -drawRect: method, we allow UIKit to continue to implement 
    // this logic, while doing our real drawing work inside of -drawLayer:inContext: 
} 

// These calls inside this method are thread SAFE 
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context 
{ 
    // Do all your drawing here. Do not use UIGraphics to do any drawing, use Core Graphics instead. 
    CGContextScaleCTM(context, 1.0f, -1.0f); 
    CGContextSelectFont(context, [self.font.fontName UTF8String], self.font.pointSize, kCGEncodingMacRoman); 
    CGContextSetTextDrawingMode(context, kCGTextFill); 
// CGContextSetShouldAntialias(context, true); 
    CGContextSetFillColorWithColor(context, [[[UIColor blackColor] colorWithAlphaComponent:0.75f] CGColor]); 
    CGContextShowTextAtPoint(context, shadowDrawPoint.x, shadowDrawPoint.y, [self.text UTF8String], self.text.length); 
    CGContextSetFillColorWithColor(context, [self.textColor CGColor]); 
    CGContextShowTextAtPoint(context, textDrawPoint.x, textDrawPoint.y, [self.text UTF8String], self.text.length); 
} 

@end 
2

這是我對召喚的答案,它使用的核心文本來解決問題,用英語以外的語言(雖然我只測試瑞典)和奇字體符號。請注意,它使用initWithCoder,因爲我使用的是StoryBoard。它還展示瞭如何將標籤中的文字水平居中(在垂直方向運氣不多,我只需測試我的方式以適合正確的位置)。

頁眉:

#import <UIKit/UIKit.h> 
#import <QuartzCore/QuartzCore.h> 

@interface DNLabel : UILabel 

@end 

實現:

#import "DNLabel.h" 
#import <CoreText/CoreText.h> 

@implementation DNLabel 

+ (Class)layerClass 
{ 
    return [CATiledLayer class]; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    if (self) 
    { 
     [self setupView]; 
    } 
return self; 
} 

-(void)awakeFromNib 
{ 
    [super awakeFromNib]; 
    [self setupView]; 
} 

- (void)setupView { 
CATiledLayer *layerForView = (CATiledLayer *)self.layer; 
layerForView.levelsOfDetailBias = 10; 
layerForView.levelsOfDetail = 10; 
} 

// LEAVE IT EMPTY 
-(void)drawRect:(CGRect)r 
{ 
// UIView uses the existence of -drawRect: to determine if should allow its CALayer 
// to be invalidated, which would then lead to the layer creating a backing store and 
// -drawLayer:inContext: being called. 
// By implementing an empty -drawRect: method, we allow UIKit to continue to implement 
// this logic, while doing our real drawing work inside of -drawLayer:inContext: 
} 

// These calls inside this method are thread SAFE 
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context 
{ 
    // Core Text version 
    CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)self.font.fontName, 
              self.font.pointSize, 
              NULL); 
    // set color 
    CGColorRef color = [[[UIColor blackColor] colorWithAlphaComponent:0.75f] CGColor]; 

    // pack it into attributes dictionary 
    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys: 
            (id)CFBridgingRelease(ctFont), (id)kCTFontAttributeName, 
            color, (id)kCTForegroundColorAttributeName, 
            nil, (id)kCTUnderlineStyleAttributeName, nil]; 

    // make the attributed string 
    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:self.text 
                    attributes:attributesDict]; 
    // flip the coordinate system 
    CGContextSetTextMatrix(context, CGAffineTransformIdentity); 
    CGContextTranslateCTM(context, 0, self.bounds.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    // check size of text and set position centered horizontally 
    CGSize size = [self.text sizeWithFont:self.font]; 
    CGContextSetTextPosition(context, self.bounds.size.width/2 - size.width/2, 1); 

    // draw 
    CTLineRef line = CTLineCreateWithAttributedString(
                (CFAttributedStringRef)CFBridgingRetain(stringToDraw)); 
    CTLineDraw(line, context); 
} 

@end 
+0

很好地完成。你提供的代碼是NSAttributedString,這是我的解決方案的一個很好的補充。我認爲提供的解決方案適用於任何字體和語言。在我的項目中,我使用提供的自定義字體代碼。如果您確實相信,請將問題標記爲已回答。 – Summon

+0

我也在使用自定義字體,但當標籤有瑞典字母時,它的回答也崩潰了,它也沒有顯示一些符號/等等。我不認爲我可以將問題標記爲已回答,因爲我沒有張貼它,但很高興我找到了解決方案。 –

相關問題