簡體   English   中英

為什么我的 NSMutableString 編輯有時不起作用?

[英]Why does my NSMutableString edit sometimes not work?

我正在嘗試修復一些編號錯誤的電影字幕文件(每個子字幕由空行分隔)。 以下代碼掃描到測試文件中錯誤的字幕索引號。 如果我只是“打印”有故障的索引並替換索引,一切都會按預期顯示。

//######################################################################
-(IBAction)scanToSubIndex:(id)sender
{
    NSMutableString* tempString = [[NSMutableString alloc] initWithString:[theTextView string]];
    int textLen = (int)[tempString length];
    
    NSScanner *theScanner = [NSScanner scannerWithString:tempString];
    while ([theScanner isAtEnd] == NO)
        {
        [theScanner scanUpToString:@"\r\n\r\n" intoString:NULL];
        [theScanner scanString:@"\r\n\r\n" intoString:NULL];
        
        if([theScanner scanLocation] >= textLen)
            break;
        else
            { // remove OLD subtitle index...
            NSString *oldNumStr;
            [theScanner scanUpToString:@"\r\n" intoString:&oldNumStr];
printf("old number:%s\n", [oldNumStr UTF8String]);                
            NSRange range = [tempString rangeOfString:oldNumStr];
                [tempString deleteCharactersInRange:range];

            // ...and insert SEQUENTIAL index
            NSString *newNumStr = [self changeSubIndex];
printf("new number:%s\n\n", [newNumStr UTF8String]);
                [tempString insertString:newNumStr atIndex:range.location];
            }
        }
printf("\ntempString\n\n:%s\n", [tempString UTF8String]);
}

//######################################################################
-(NSString*)changeSubIndex
{
    static int newIndex = 1;
    // convert int to string and return...
    NSString *numString = [NSString stringWithFormat:@"%d", newIndex];
        ++newIndex;
    
return numString;
}

但是,當我嘗試將新索引寫入靜音字符串時,最終會得到如下無序的結果:

sub 1

sub 2

sub 3

sub 1

sub 5

sub 6

sub 7

sub 5

sub 9

sub 7

sub 8

一個有趣的觀察結果(和可能的線索?)是,當我達到字幕編號 1000時,每個數字都會根據需要按順序寫入可變字符串。 我已經為此苦苦掙扎了幾個星期,而且我在 SO 上找不到任何其他類似的問題。 非常感謝任何幫助:-)

NSScanner & NSMutableString

NSMutableStringNSString的子類。 換句話說,您可以在需要NSString的地方傳遞NSMutableString 但這並不意味着您可以修改它。

scannerWithString:需要NSString 翻譯成人類語言 - 我期望一個字符串,我也期望該字符串是只讀的(不會被修改)。

換句話說 - 你的代碼被認為是程序員錯誤 - 你給NSScanner一些東西, NSScanner期望不可變的字符串,你正在修改它。

我們不知道NSScanner class 在幕后做什么。 可以有緩沖或任何其他類型的優化。

即使您對提到的scanLocation修復(在評論中)很幸運,您也不應該依賴它,因為引擎蓋下的實現可能會隨着任何新版本而改變。

不要這樣做。 不僅在這里,而且在您看到不可變數據類型的任何地方。

(在某些情況下您可以做到這一點,但是您應該真正知道幕后實現在做什么,確保它不會被修改等。但一般來說,除非您知道自己在做什么,否則這不是一個好主意'正在做。)

樣本

此示例代碼基於以下假設:

  • 我們正在談論 SubRip 文本 (SRT)
  • 文件很小(很容易適應內存)
  • SRT文件的rest是正確的
    • 尤其是分隔符( @"\r\n"
@import Foundation;

NS_ASSUME_NONNULL_BEGIN

@interface SubRipText : NSObject

+ (NSString *)fixSubtitleIndexes:(NSString *)string;

@end

NS_ASSUME_NONNULL_END
@implementation SubRipText

+ (NSString *)fixSubtitleIndexes:(NSString *)string {
    NSMutableString *result = [@"" mutableCopy];
    
    __block BOOL nextLineIsIndex = YES;
    __block NSUInteger index = 1;
    
    [string enumerateLinesUsingBlock:^(NSString * _Nonnull line, BOOL * _Nonnull stop) {
        if (nextLineIsIndex) {
            [result appendFormat:@"%lu\r\n", (unsigned long)index];
            index++;
            nextLineIsIndex = NO;
            return;
        }
        
        [result appendFormat:@"%@\r\n", line];
        
        nextLineIsIndex = line.length == 0;
    }];
    
    return result;
}

@end

用法:

NSString *test = @"29\r\n"
"00:00:00,498 --> 00:00:02,827\r\n"
"Hallo\r\n"
"\r\n"
"4023\r\n"
"00:00:02,827 --> 00:00:06,383\r\n"
"This is two lines,\r\n"
"subtitles rocks!\r\n"
"\r\n"
"1234\r\n"
"00:00:06,383 --> 00:00:09,427\r\n"
"Maybe not,\r\n"
"just learn English :)\r\n";

NSString *result = [SubRipText fixSubtitleIndexes:test];

NSLog(@"%@", result);

Output:

1
00:00:00,498 --> 00:00:02,827
Hallo

2
00:00:02,827 --> 00:00:06,383
This is two lines,
subtitles rocks!

3
00:00:06,383 --> 00:00:09,427
Maybe not,
just learn English :)

還有其他方法可以實現這一點,但您應該考慮可讀性、寫入速度、運行速度……取決於您的使用情況——您要修復其中的多少,等等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM