Создайте NSMutableArray из NSRange и правильно прочитайте значения диапазона позже

Я пытаюсь создать NSMutableArray диапазонов, обнаруженных из NSRegularExpression, но не могу заставить NSMutableArray хранить объекты. Помощь?

Объявите массив: NSMutableArray *matches = [[NSMutableArray alloc]init];

В конце моих циклов регулярных выражений:

for (NSTextCheckingResult *aMatch in minedMatches) {
    NSRange matchRange = [aMatch range];
    [matches addObject: [NSValue valueWithRange:matchRange]];
}

В другой части моего кода у меня есть цикл for, который хочет использовать matches; однако он не полный:

if (matches != nil) {
            for (int i = 0; i < matches.count; i++) {
                [attributedString addAttribute:NSForegroundColorAttributeName value: minedColor range:[[matches objectAtIndex:i]rangeValue]]; 
            }
        }

**Примечание:

minedColor, minedMatches и attributedString правильно объявлены во всем моем коде. Я использую addAttribute в отдельном месте, потому что мне нужно только изменить цвет текста между разделами ключевых слов, таких как «Go» и «end».

**Редактировать 1 (запрос всего метода)

- (void)textViewDidChange:(UITextView *)textView {

self.notepadTextView.font = [UIFont fontWithName:@"ProximaNova-Regular" size:20]; //custom font
UIFont *normalFont = [UIFont fontWithName:@"ProximaNova-Regular" size:20];//fail-safe font for attributed string
NSString *textEntryContents = [[self notepadTextView ]text]; //declares user inputted string
[gCore processSpeechText:textEntryContents]; //internal processing
NSMutableArray *mined = [gCore getHighLightContainer]; //array with strings that need to be colored
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:textEntryContents
                                                                                     attributes:@{NSFontAttributeName: normalFont}]; //initialize attributed string
matches = [[NSMutableArray alloc]init]; //initialize matches
UIColor *minedColor = [UIColor colorWithRed:(126.0/255.0) green:(204.0/255.0) blue:(136.0/255.0) alpha:1.0]; //initialize color for attributed string

BOOL colorChangeDidRun = '\0'; //initialize if color was changed

if ([gCore dataMiningInProgress] == YES) { //if it is the start of a section
    colorChangeDidRun = NO; 
    if (mined != nil){ //fail-safe
        for (int i = 0; i < mined.count; i++){
            NSError *regexErrorMined;
            NSRegularExpression *regexMined = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"%@",mined[i]]
                                                                                        options:NSRegularExpressionCaseInsensitive error:&regexErrorMined];
            if (!regexErrorMined) {
                NSArray *minedMatches = [regexMined matchesInString:[attributedString string]
                                                            options:0
                                                              range:NSMakeRange(0, [[attributedString string] length])];
                for (NSTextCheckingResult *aMatch in minedMatches) {
                    NSRange matchRange = [aMatch range];
                    [matches addObject: [NSValue valueWithRange:matchRange]]; //add range values to matches array                     
                }
            }
        }

    }

}
else if ([gCore dataMiningInProgress] == NO) { //if end of section
    if (colorChangeDidRun == NO) { //if the color change has not happened yet
        if (matches != nil) {
            for (int i = 0; i < matches.count; i++) {
                colorChangeDidRun = YES; //prevent color change in unnecessary spots
                [attributedString addAttribute:NSForegroundColorAttributeName value: minedColor range:[[matches objectAtIndex:i]rangeValue]];            
            }
        }
    }
}

self.notepadTextView.attributedText = attributedString; //output attributed string

}

Первоначально я не публиковал весь метод, потому что он требует много объяснений, как, я уверен, вы можете видеть. По сути, пользователь будет вводить текст в текстовое представление. Затем этот текст извлекается из данных, если слова попадают между «Начало» и «Конец». Эти ключевые слова сигнализируют о триггерах, которые изменяют значение [gCore dataMiningInProgress], являющегося глобальным объектом.

В настоящее время, если пользователь введет «Начать кота снаружи конца», слова «кошка» и «снаружи» изменят цвет, когда пользователь введет «конец». Если пользователь вводит дополнительную строку, например: «Начать кота сейчас внутри конца», слово «кошка» автоматически станет зеленым еще до того, как пользователь введет «конец». Я хочу предотвратить это. Я хочу, чтобы цвет менялся только в отдельных разделах «начало……конец».

Все внешние переменные находятся в рабочем состоянии, единственное, что я пока не могу получить, это addAttribute из массива диапазонов в matches, потому что, хотя это не говорит, что это nil, matches.count равно 0 в условном выражении else if().


person momodude22    schedule 09.07.2014    source источник
comment
Определение не полное. И является ли matches локальной переменной или переменной экземпляра?   -  person rmaddy    schedule 09.07.2014
comment
И вы подтвердили, что вы действительно получаете действительный matchRange при добавлении? Поместите точку останова отладки на [соответствует addObject:] и посмотрите, увеличивается ли количество объектов сразу после   -  person LyricalPanda    schedule 09.07.2014
comment
Кроме того, вы уверены, что цикл for в вашем первом примере кода действительно выполняется, и объекты добавляются в массив совпадений?   -  person timgcarlson    schedule 09.07.2014
comment
Нельзя ли использовать minedMatches или просто скопировать?   -  person Larme    schedule 09.07.2014
comment
не может заставить NSMutableArray хранить объекты, не является адекватным описанием проблемы. Вы не определили конкретную проблему и уж точно не охарактеризовали ее должным образом.   -  person Hot Licks    schedule 09.07.2014
comment
Если я добавлю NSLog в первый пример кода, чтобы увидеть match.count, он фактически зарегистрирует правильное количество объектов. При этом, если бы я добавил тот же NSLog в код прямо перед addAttribute, счетчик записался бы как 0. @LyricalPanda @timgcarlson   -  person momodude22    schedule 09.07.2014
comment
Вероятно, это потому, что matches равно нулю.   -  person Hot Licks    schedule 09.07.2014
comment
@rmaddy, в настоящее время matches объявлен внутри метода -(void)textViewDidChange вместе с остальными NSRegularExpression циклами и кодом. Я попытался сделать matches свойством класса и написать об этом, но я тоже не смог заставить это работать.   -  person momodude22    schedule 09.07.2014
comment
Использование локальной переменной никогда не сработает, потому что ее нельзя использовать в других методах. Используйте частное свойство или переменную экземпляра.   -  person rmaddy    schedule 09.07.2014
comment
фрагменты кода в посте выглядят правильно. Не могли бы вы перечислить полную реализацию метода -textViewDidChange?   -  person kambala    schedule 09.07.2014
comment
Извините, если я не понял, но часть кода addAttributes находится в том же методе, что и объявление кода matches и кода NSRegualrExpression, поэтому я думал, что локальная переменная будет работать? @rmaddy   -  person momodude22    schedule 09.07.2014
comment
Нет, было совершенно непонятно, что оба куска кода и объявление matches находятся в одной области видимости. Обновите свой вопрос, чтобы показать полную область, показывающую, как инициализируется matches, и все места, где он используется. И вы так и не сказали нам, в чем собственно проблема. matches nil? Если нет, то есть ли в нем какие-либо объекты?   -  person rmaddy    schedule 09.07.2014


Ответы (2)


У вас здесь очень простая ошибка: невозможно выполнить обе ветви if и else if за один проход. Так что если [gCore dataMiningInProgress] == YES то только matches будет заполнено объектами и все. Если условие NO, то matches - это пустой массив (потому что он явно не был заполнен объектами).

P.S. Бесполезно писать if ([gCore dataMiningInProgress] == YES) ... else if ([gCore dataMiningInProgress] == NO), потому что если оно не дает YES, то это определенно NO :) Так что это просто конструкция if-else.

person kambala    schedule 09.07.2014
comment
Я даже не подумал о if-else второстепенной детали, так что спасибо за это! Что бы вы посоветовали о том, как получить доступ к matches в разделе else, не будучи пустым массивом? Я попытался объявить matches в моем файле .h, а затем синтезировать его, но это тоже не сработало :/ - person momodude22; 09.07.2014
comment
@momodude22 momodude22 Это действительно зависит от потока вашего кода. Вы хотите, чтобы совпадения сохранялись с каждым textDidChange? Затем добавьте его как свойство и инициализируйте массив в viewDidLoad и removeAllObjects при выходе из textView. Если вы не хотите, чтобы он сохранялся, отбросьте if/else. - person LyricalPanda; 09.07.2014
comment
Я успешно изменил цвет слов без if-else, но проблема здесь в том, что начальное изменение цвета происходит после того, как пользователь набрал end. Если после этого они начнут новый раздел, набрав Start, изменение цвета произойдет по мере того, как пользователь будет вводить текст в режиме реального времени, ДО того, как он наберет end, если это слово было введено в предыдущем разделе. Я не хочу, чтобы он автоматически менял цвет, если его видели раньше, я бы хотел, чтобы он менял цвета только после того, как пользовательские типы заканчиваются, поэтому я полагал, что операторы if-else были необходимы @LyricalPanda - person momodude22; 09.07.2014
comment
@momodude22, затем сохраните свой массив диапазонов в свойстве и примените окраску только после того, как будет введен end (проверьте последние символы текста textview или что-то еще) - person kambala; 09.07.2014

Используя предложения от @kambala и @LyricalPanda, моя первоначальная проблема matches, являющаяся nil в выражении else, была решена с помощью проблемы области видимости. Хотя я создал свойство в заголовочном файле для matches и @synthesize сделал его, мой NSMutableArray не записывался на уровне класса. Я изменил область действия, чтобы создать глобальную переменную для matches, к которой теперь можно получить доступ из любого файла. Похоже на пустую трату мощности кодирования, но именно так я смог заставить MutableArray хранить объекты за пределами одного экземпляра. Использование команды @extern позволяет успешно читать и записывать массив, полный диапазонов.

person momodude22    schedule 10.07.2014