2
This commit is contained in:
@@ -312,7 +312,7 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
|
||||
- (void)kb_startNetworkStreamingWithSeed:(NSString *)seedTitle fallbackToMock:(BOOL)fallback {
|
||||
[self kb_stopNetworkStreaming];
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) { if (fallback) [self kb_startMockStreamingWithSeed:seedTitle]; return; }
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) { if (fallback) /*[self kb_startMockStreamingWithSeed:seedTitle]*/; return; }
|
||||
|
||||
NSURL *url = [NSURL URLWithString:kKBStreamDemoURL];
|
||||
if (!url) { if (fallback) [self kb_startMockStreamingWithSeed:seedTitle]; return; }
|
||||
@@ -323,8 +323,10 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
// 由本类统一做 /t->\t 与首段去 \t,fetcher 只负责增量与协议解析
|
||||
fetcher.disableCompression = YES;
|
||||
fetcher.acceptEventStream = NO; // 响应头若是 SSE 仍会自动解析
|
||||
fetcher.treatSlashTAsTab = NO;
|
||||
fetcher.trimLeadingTabOnce = NO;
|
||||
// 将 \t 与首段去 \t 的处理下沉到 Fetcher,避免 UI 抖动
|
||||
fetcher.treatSlashTAsTab = YES;
|
||||
fetcher.trimLeadingTabOnce = YES;
|
||||
fetcher.flushInterval = 0.05; // 更接近“立刻显示”的节奏
|
||||
fetcher.onChunk = ^(NSString *chunk) {
|
||||
__strong typeof(weakSelf) self = weakSelf; if (!self) return;
|
||||
[self kb_appendChunkToStreamView:chunk];
|
||||
@@ -351,27 +353,11 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
#pragma mark - Helpers
|
||||
|
||||
/// 统一处理需要输出到 KBStreamTextView 的分片:
|
||||
/// - 将 "/t" 转为真正的制表符 "\t";
|
||||
/// - 若这是首段输出且文本起始(允许有前导空白)紧跟一个 "\t",只删除这一个;
|
||||
/// - 非空才追加到视图,并标记已输出。
|
||||
/// - 目前网络层(KBStreamFetcher)已做 “/t->\t、首段去一个 \t、段间去一个空格”
|
||||
/// - 这里仅负责附加到视图与标记首段状态,避免 UI 抖动
|
||||
- (void)kb_appendChunkToStreamView:(NSString *)chunk {
|
||||
if (chunk.length == 0 || !self.streamTextView) return;
|
||||
NSString *text = [chunk stringByReplacingOccurrencesOfString:@"/t" withString:@"\t"];
|
||||
if (!self.streamHasOutput) {
|
||||
NSUInteger i = 0; // 跳过前导空白
|
||||
while (i < text.length) {
|
||||
unichar c = [text characterAtIndex:i];
|
||||
if (c == ' ' || c == '\r' || c == '\n') { i++; continue; }
|
||||
break;
|
||||
}
|
||||
if (i < text.length && [text characterAtIndex:i] == '\t') {
|
||||
NSMutableString *m = [text mutableCopy];
|
||||
[m deleteCharactersInRange:NSMakeRange(i, 1)];
|
||||
text = m;
|
||||
}
|
||||
}
|
||||
if (text.length == 0) return;
|
||||
[self.streamTextView appendStreamText:text];
|
||||
[self.streamTextView appendStreamText:chunk];
|
||||
self.streamHasOutput = YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,20 @@
|
||||
[self addSubview:_scrollView];
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
// 仅去掉末尾空白/换行(保留前导空白,避免“段落在完成时向左跳动”)
|
||||
static inline NSString *KBTrimRight(NSString *s) {
|
||||
if (s.length == 0) return s;
|
||||
NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
||||
NSInteger end = (NSInteger)s.length - 1;
|
||||
while (end >= 0 && [set characterIsMember:[s characterAtIndex:(NSUInteger)end]]) {
|
||||
end--;
|
||||
}
|
||||
if (end < 0) return @"";
|
||||
return [s substringToIndex:(NSUInteger)end + 1];
|
||||
}
|
||||
|
||||
#pragma mark - Public API
|
||||
|
||||
// 边输边见:实时更新当前 label 文本,遇到分隔符就新建下一个 label
|
||||
@@ -98,14 +112,11 @@
|
||||
self.labels.lastObject.text = self.buffer; // 不裁剪,保留实时输入
|
||||
[self layoutLabelsForCurrentWidth];
|
||||
|
||||
// 2) 处理每一个分隔符:完成当前段(可选裁剪)并新建空标签,然后填入下一段的内容
|
||||
// 2) 处理每一个分隔符:完成当前段(仅裁剪“末尾空白”)并新建空标签,然后填入下一段的内容
|
||||
for (NSUInteger i = 1; i < parts.count; i++) {
|
||||
// a) 完成当前段:对外观进行最终裁剪(若开启)
|
||||
UILabel *current = self.labels.lastObject;
|
||||
if (self.shouldTrimSegments) {
|
||||
NSString *trimmed = [current.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
current.text = trimmed;
|
||||
}
|
||||
if (self.shouldTrimSegments) { current.text = KBTrimRight(current.text ?: @""); }
|
||||
[self layoutLabelsForCurrentWidth];
|
||||
|
||||
// b) 新建一个空标签,代表下一个段(即刻创建,哪怕下一段当前为空)
|
||||
@@ -133,9 +144,7 @@
|
||||
#pragma mark - Layout Helpers
|
||||
|
||||
- (void)addLabelForText:(NSString *)text {
|
||||
if (self.shouldTrimSegments) {
|
||||
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
}
|
||||
if (self.shouldTrimSegments) { text = KBTrimRight(text ?: @""); }
|
||||
// 创建一个可换行、可点击的 UILabel
|
||||
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
label.numberOfLines = 0;
|
||||
@@ -195,7 +204,7 @@
|
||||
UILabel *current = self.labels.lastObject;
|
||||
if (!current) { return; }
|
||||
if (self.shouldTrimSegments) {
|
||||
NSString *trimmed = [current.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
NSString *trimmed = KBTrimRight(current.text ?: @"");
|
||||
current.text = trimmed;
|
||||
self.buffer = trimmed;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user