I have defined a method appendString method in a NSMuatableAttributedString category like this:
@implementation NSMutableAttributedString (HTML)
// appends a plain string extending the attributes at this position
- (void)appendString:(NSString *)string
{
NSParameterAssert(string);
NSUInteger length = [self length];
...
And this method is worked well in iOS17 and before .
But when it cames iOS18 . this appendString will not be called.
So I doubt maybe there is a system-defined appendString already.
So I write a demo in empty project to print all the NSMuatableAttributedString method in iOS18 like these:
@interface ViewController ()
@end
@implementation ViewController
void printNSStringCategories() {
unsigned int count;
Class nsStringClass = [NSMutableAttributedString class];
// 获取所有的方法
Method *methods = class_copyMethodList(nsStringClass, &count);
for (unsigned int i = 0; i < count; i++) {
SEL selector = method_getName(methods[i]);
NSString *methodName = NSStringFromSelector(selector);
NSLog(@"NSMutableAttributedString method: %@", methodName);
}
free(methods);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
printNSStringCategories();
}
And test it in my iPhone (iOS18.2) , the log will printed
NSMutableAttributedString method: appendString:withAttributes:
NSMutableAttributedString method: cr_appendStorage:fromRange:
NSMutableAttributedString method: cr_appendString:
NSMutableAttributedString method: appendString:withAttributes:
NSMutableAttributedString method: appendString:
So it seems a appendString: is aleady defined in system SDK .
But the weird thing is when I run this code in the Xcode simulator (iOS18.1) this appendString: will not print .
1 Is it a bug of SDK ? because the appendString: only exist in device-build , and not exist in simulator-build?
two more furthur question:
2.1 if the SDK contains appendString: already , why the appendString: defined in my category not cause the duplicate symbol error when compile
2.2 As the question 2.1 said , there maybe same symbols in runtime . Is there any way to find the framework/library which defined those same-name symbols ? (e.g: there are two appendString:withAttributes: in the log , I want to find the two places define each appendString:withAttributes: exactly)
Post
Replies
Boosts
Views
Activity
demo code :
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
NSDictionary *attrs = @{NSFontAttributeName: [UIFont systemFontOfSize:20],
NSForegroundColorAttributeName: [UIColor blueColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleThick),
};
// Make an attributed string
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:@"Hello CoreText!" attributes:attrs];
CFAttributedStringRef attributedStringRef = (__bridge CFAttributedStringRef)attributedString;
// Simple CoreText with CTFrameDraw
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributedStringRef);
CGPathRef path = CGPathCreateWithRect(self.bounds,NULL);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0, 0),path,NULL);
//CTFrameDraw(frame, context);
// You can comment the line 'CTFrameDraw' and use the following lines
// draw with CTLineDraw
CFArrayRef lines = CTFrameGetLines(frame);
CGPoint lineOrigins[CFArrayGetCount(lines)];
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
for (int i = 0; i < CFArrayGetCount(lines); i++) {
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGContextSetTextPosition(context, lineOrigins[i].x, lineOrigins[i].y);
// CTLineDraw(line, context);
// You can comment the line 'CTLineDraw' and use the following lines
// draw with CTRunDraw
// use CTRunDraw will lost some attributes like NSUnderlineStyleAttributeName,
// so you need draw it by yourself
CFArrayRef runs = CTLineGetGlyphRuns(line);
for (int j = 0; j < CFArrayGetCount(runs); j++) {
CTRunRef run = CFArrayGetValueAtIndex(runs, j);
CTRunDraw(run, context, CFRangeMake(0, 0));
}
}
}
this code will use CTRunDraw to draw the content , and the underline will draw and show normally in iOS17 & Xcode 15 , But when you build it with XCode16 & iOS18 beta . the underline will be missing .
After updating to Xcode 15.3 , Xcode will crash soon after open my project , and my project works fine for years and after I reset Xcode to 15.2 . my project can work well . so I think this is a problem brought by Xcode 13
-------------------------------------
Translated Report (Full Report Below)
-------------------------------------
Process: Xcode [26747]
Path: /Applications/Xcode.app/Contents/MacOS/Xcode
Identifier: com.apple.dt.Xcode
Version: 15.3 (22618)
Build Info: IDEApplication-22618000000000000~2 (15E204a)
App Item ID: 497799835
App External ID: 863955376
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
User ID: 501
Date/Time: 2024-03-28 15:34:04.5862 +0800
OS Version: macOS 14.1.1 (23B81)
Report Version: 12
Anonymous UUID: 0B2BF703-3E8D-CF6D-2498-8380353F5495
Time Awake Since Boot: 1400 seconds
System Integrity Protection: enabled
Crashed Thread: 0
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000019b43065c
Termination Reason: Namespace SIGNAL, Code 5 Trace/BPT trap: 5
Terminating Process: exc handler [26747]
Thread 0 Crashed:
0 libswiftCore.dylib 0x19b43065c _assertionFailure(_:_:file:line:flags:) + 268
1 IDEXCBuildSupportCore 0x178f5ea3c specialized _NativeDictionary.merge<A>(_:isUnique:uniquingKeysWith:) + 928
2 IDEXCBuildSupportCore 0x178f66320 specialized IDEXCBuildServiceBuildOperation.processEventStream(buildOperation:events:logger:context:) + 1164
3 IDEXCBuildSupportCore 0x178f6f885 closure #1 in closure #3 in IDEXCBuildServiceBuildOperation.performCoreBuild() + 1
4 IDEXCBuildSupportCore 0x178f62f5d partial apply for closure #1 in closure #3 in IDEXCBuildServiceBuildOperation.performCoreBuild() + 1
5 IDEXCBuildSupportCore 0x178f261b9 specialized thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) + 1
6 IDEXCBuildSupportCore 0x178f26891 partial apply for specialized thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) + 1
7 libswift_Concurrency.dylib 0x22ad89c7d completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1
I think the most important feature for iOS native-developers is the Hot-Update(Because it's so hard to force your app's users to upgrade in AppStore), And this is the reason why so many cross-platform technologies are needed . Is there any chances that Apple will issue a official Hot-Upgrade mechanism for this ? And I think it's not very hard to Apple to achieve this .
I found that ,If a Parent View was CATiledLayer based, it will deallocating its SubView's layer before the SubView object is deallocating it self (When SubView object is retained in some async opertaions, and Parent View is deallocating). This can cause some zombie memory issues. If the Parent View is CALayer based , everything is OK.
I have done a zombie profiling for both layers situations.
Seems the only diffrence between them is _UIViewWillBeRemovedFromSuperview will be called only for CALayer based ParentView ,
and without _UIViewWillBeRemovedFromSuperview called , the SubView's layer object 's reference count seem wrong and the zombie object comes out
demo code can be found here:
demo code - https://github.com/ximmyxiao/TestTiledLayerDealloc
It seems that addSubView is not permit for CATiledLayer based View?
I have just update Xcode to Xcode 12.3 , and my project can't compile , it complains:
Building for iOS Simulator, but the linked and embedded framework 'ITLogin.framework' was built for iOS + iOS Simulator.
This framework is worked well before Xcode 12.3 , so what's the problem here ?