Skip to content

Instantly share code, notes, and snippets.

@g761007
Last active September 23, 2021 08:54
Show Gist options
  • Save g761007/9f12c5de4d77de8cff74ea9456a055ff to your computer and use it in GitHub Desktop.
Save g761007/9f12c5de4d77de8cff74ea9456a055ff to your computer and use it in GitHub Desktop.
解決YYLabel在IOS11文字高度計算與純中文垂直置中結果不如預期的問題
//
// YYTextLine+Swizzle.h
// Created by Daniel Hsieh on 2018/8/1.
// REF: https://github.com/ibireme/YYText/issues/748#issuecomment-364879873
// ISSUES: https://github.com/ibireme/YYText/issues/748
//
#import "YYTextLine.h"
@interface YYTextLine (Swizzle)
@end
//
// YYTextLine+Swizzle.m
// Created by Daniel Hsieh on 2018/8/1.
// REF: https://github.com/ibireme/YYText/issues/748#issuecomment-364879873
// ISSUES: https://github.com/ibireme/YYText/issues/748
//
#import <objc/runtime.h>
#import "YYTextLine+Swizzle.h"
@implementation YYTextLine (Swizzle)
+ (void)load {
Method original, swizzled;
original = class_getInstanceMethod(objc_getClass("YYTextLine"), NSSelectorFromString(@"setCTLine:"));
swizzled = class_getInstanceMethod(self, @selector(swizzled_setCTLine:));
method_exchangeImplementations(original, swizzled);
}
- (void)swizzled_setCTLine:(_Nonnull CTLineRef)CTLine {
// _CTLine
CTLineRef *_CTLinePtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_CTLine");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CTLineRef *ptr = (CTLineRef *)(bytes+offset);
ptr;
});
// _ascent
CGFloat *_ascentPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_ascent");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
// _descent
CGFloat *_descentPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_descent");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
// _leading
CGFloat *_leadingPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_leading");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
// _lineWidth
CGFloat *_lineWidthPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_lineWidth");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
// _range
NSRange *_rangePtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_range");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
NSRange *ptr = (NSRange *)(bytes+offset);
ptr;
});
// _firstGlyphPos
CGFloat *_firstGlyphPosPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_firstGlyphPos");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
// _trailingWhitespaceWidth
CGFloat *_trailingWhitespaceWidthPtr = ({
Ivar ivar = class_getInstanceVariable([self class], "_trailingWhitespaceWidth");
ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char* bytes = (unsigned char *)(__bridge void*)self;
CGFloat *ptr = (CGFloat *)(bytes+offset);
ptr;
});
if (*_CTLinePtr != CTLine) {
if (CTLine) CFRetain(CTLine);
if (*_CTLinePtr) CFRelease(*_CTLinePtr);
*_CTLinePtr = CTLine;
if (*_CTLinePtr) {
*_lineWidthPtr = CTLineGetTypographicBounds(*_CTLinePtr, _ascentPtr, _descentPtr, _leadingPtr);
if (@available(iOS 11.0, *)) {
CGRect tempRect = CTLineGetBoundsWithOptions(*_CTLinePtr, 0);
if (*_descentPtr > tempRect.size.height) {
*_descentPtr = tempRect.size.height - *_ascentPtr;
}
}
CFRange range = CTLineGetStringRange(*_CTLinePtr);
*_rangePtr = NSMakeRange(range.location, range.length);
if (CTLineGetGlyphCount(*_CTLinePtr) > 0) {
CFArrayRef runs = CTLineGetGlyphRuns(*_CTLinePtr);
CTRunRef run = CFArrayGetValueAtIndex(runs, 0);
CGPoint pos;
CTRunGetPositions(run, CFRangeMake(0, 1), &pos);
*_firstGlyphPosPtr = pos.x;
} else {
*_firstGlyphPosPtr = 0;
}
*_trailingWhitespaceWidthPtr = CTLineGetTrailingWhitespaceWidth(*_CTLinePtr);
} else {
*_lineWidthPtr = *_ascentPtr = *_descentPtr = *_leadingPtr = *_firstGlyphPosPtr = *_trailingWhitespaceWidthPtr = 0;
*_rangePtr = NSMakeRange(0, 0);
}
// [self reloadBounds];
SEL sel = NSSelectorFromString(@"reloadBounds");
IMP imp = class_getMethodImplementation(objc_getClass("YYTextLine"), sel);
((void(*)(id, SEL))imp)(self, sel);
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment