355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Стивен Кочан » Программирование на Objective-C 2.0 » Текст книги (страница 19)
Программирование на Objective-C 2.0
  • Текст добавлен: 19 сентября 2016, 13:02

Текст книги "Программирование на Objective-C 2.0"


Автор книги: Стивен Кочан



сообщить о нарушении

Текущая страница: 19 (всего у книги 32 страниц)

Вывод программы 15.5 This is string А (Это строка A) This is mutable string А (Это мутабельная строка A) This is mutable string A and string В (Это мутабельные строка А и строка В) This is mutable string A and string В and string С (Это мутабельные строка А, строка В и строка С) This is mutable string В and string С (Это мутабельные строка В и строка С) This is mutable string С (Это мутабельная строка С) This is string А (Это строка А) This is a mutable string (Это мутабельная строка) An example of a mutable string An exXmple of X mutXble string

Объявление NSMutableString *mstr;

определяет mstr как переменную со строковым объектом, содержимое которого может изменяться во время выполнения программы. В операторе mstr = [NSMutableString stringWithString: strl];

переменной mstr присваивается строковый объект, содержимое которого является копией символов, содержащихся в strl, то есть 'This is string А". Если метод stringWithString: передается классу NSMutableString, возвращаемым результатом является мутабельный строковый объект. Если он передается классу NSString, как в программе 15.5, то мы получаем немутабельный строковый объект.

Метод insertString:atlndex: выполняет вставку указанной символьной строки в строку-получатель, начиная с указанного индекса (порядкового номера). В данном случае выполняется вставка mutable" в строку, начиная с индекса 7, то есть перед восьмым символом строки. В отличие от методов для немутабель– ных строковых объектов, никакого значения не возвращается, поскольку модифицируется строка-получатель. При втором вызове insertstring:atlndex: используется метод length для вставки одной символьной строки в конец другой. Метод appendString: позволяет выполнить эту задачу несколько проще.

С помощью метода deleteCharactersInRange: можно удалить заданное число символов из строки. Применение диапазона (16, 13) к строке This is mutable string A and string В and string C

позволяет удалить 13 символов "string A and", начиная с индекса 16 (то есть с 17-го символа строки). Это показано на рис. 15.1.

Рис. 15.1. Индексы позиций в строке

В следующих строках программы 15.5 метод rangeOfString: позволяет сначала найти строку, а затем удалить ее. После проверки, что строка @"string В and" действительно содержит mstr, применяется метод deleteCharactersInRange: для удаления этих символов с использованием диапазона, возвращаемого методом rangeOfString:, в качестве аргумента.

Метод setString: применяется для непосредственного задания содержимого мутабельного строкового объекта. После присвоения строки <§>'This is string А" несколько символов этой строки заменяются другой строкой с помощью метода replaceCharacterstnRange:. Размеры заменяемой и заменяющей строк могут быть неодинаковыми; одну строку можно заменить строкой равного или неравного размера. Например, в операторе [mstr replaceCharacterstnRange: NSMakeRange(8, 8) withString: @"a mutable string"];

8 символов "string А" заменяются на 16 символов "a mutable string".

В остальной части этой программы показано, как выполнять операции поиска и замены. В первом случае внутри строки mstr ищется строка @"This is" (сначала mstr была присвоена строка @This is a mutable string"). Эта строка находится в строке поиска и заменяется строкой @"An example of". В результате содержимое mstr заменяется строкой @"An example of a mutable string".

Далее в программе выполняется цикл, показывающий, как выполнить опе-рацию «найти и заменить все». Строке поиска присваивается значение @"а", и строке замены присваивается значение @Т*,

Если строка замены содержит также строку поиска (например, нужно заменить строку "а" на строку "аХ"), то мы получим бесконечный цикл.

Во-вторых, в случае пустой строки замены (когда она не содержит никаких символов) мы фактически удаляем все экземпляры строки поиска. Пустая кон-стантная символьная строка задается парой смежных кавычек без пробелов: replace = @"";

Конечно, если мы хотим просто удалить экземпляр сгроки, то можно ис-пользовать метод deleteCharactersInRange:.

И, наконец, класс NSMutahleString содержит метод с именем replaceOccurrencesOfString:withString:options:range: для операции «найти и заменить все» в строке. Цикл while программы 15.5 можно было бы заменить одним оператором. [mstr replaceOccurrencesOfString: search withString: replace options: nil range: NSMakeRange (0, [mstr length])];

Так можно избежать бесконечного цикла, поскольку это предусмотрено в самом методе. Откуда берутся все эти объекты?

В программах 15.4 и 15.5 выполняется работа со многими строковыми объектами, которые создаются и возвращаются разными методами классов NSString и NSMutableString. Вам не нужно думать об освобождении памяти, занимаемой эти-ми объектами; это предусмотрено в методах-создателях объектов. Предполага-ется, что создатели добавили все эти объекты в автоматически высвобождаемый пул (autorelease-пул), и объекты будут высвобождены, когда будет высвобожден сам пул. Однако если вы разрабатываете программу, которая создает много временных объектов, то память, используемая ими, может накапливаться. В таких случаях, возможно, придется освобождать память во время выполнения программы. Это описывается в главе 17, На данный момент просто учтите, что объекты занимают намять, которая может увеличиваться по мере выполнения программы.

Класс NSString содержит более 100 методов, которые могут работать с нему– табельными строковыми объектами. В таблице 15.2 приводятся наиболее рас-пространенные методы, а в таблице 15.3 – некоторые дополнительные методы из класса NSMutableString. Другие важные методы класса NSString (например, ра-ботающие с именами путей и читающие содержимое файла в строку) будут вво-диться далее.

В таблицах 15.2 и 15.3, url – это объект NSURL, path – это объект NSString, указывающий путь к файлу, nsstring – это объект NSString, / – это значение типа NSUInteger, представляющее допустимый номер символа в строке, епс – это объект NSStringEncoding, указывающий кодировку символов, err – это объект NSError, который описывает ошибку, если она возникла, size (размер) и орй(опции) имеют тип NSUInteger, и range – это объект NSRangc, указывающий допустимый диапазон символов в списке.

Табл. 15.2. Наиболее распространенные методы класса NSString Метод Описание +(id) stringWithContentsOfFile: path encoding; enc error: err Создает новую строку и присваивает ей содержимое файла, указанного аргументом path, в кодировке символов enc; возвращает ошибку в err, если не nil. +(id) stringWithContentsOfURL: url encoding: enc error: err Создает новую строку и присваивает ей содержимое url в кодировке символов enc, возвращает ошибку в err, если не nil. +(id) string Создает новую пустую строку +(id) stringWithString: nsstring Создает новую строку и присваивает ей nsstring. -(id) initWithString: nsstring Присваивает вновь выделяемой строке nsstring. -(id) initWithContentsOfFile: path encoding: enc error: err Присваивает строке содержимое файла, указанного аргументом path. -(id) initWithContentsOfURL: w/encoding enc error: ей Присваивает строке содержимое u//(NSURL *) в кодировке символов enc; возвращает ошибку в err, если не nil. -(NSUInteger) length Возвращает число символов в строке. -(unichar) characterAtlndex: i Возвращает символ Unicode, находящийся в позиции с индексом i -(NSString *) substringFromlndex: i Возвращает подстроку от символа с индексом i до конца. -(NSString *) siibstringWithRange: range Возвращает подстроку в соответствии с указанным диапазоном. -(NSString *) substringToIndex: i Возвращает подстроку от начала строки вплоть до символа с индексом i. -(NSComparator *) caselnsensitiveCompare: nsstring Сравнение двух строк независимо от регистра букв. -(NSComparator *) compare: nsstring Сравнение двух строк. -(BOOL) hasRrefix: nsstring Проверка, что строка начинается с nsstring. -(BOOL) hasSuffix: nsstring Проверка, что строка заканчивается nsstring. -(BOOL) isEqualToString: nsstring Проверка, что две строки равны. -(NSString *) capitalizedString Возвращает строку, делая прописной первую букву каждого слова (и строчными все остальные буквы каждого слова). -(NSString *) lowercaseString Возвращает строку, преобразованную в нижний регистр. -(NSString *) uppercaseString Возвращает строку, преобразованную в верхний регистр. -(const char *) UTF8String Возвращает строку, преобразованную в С-строку в кодировке UTF-8. -(double) doubleValue Возвращает строку, преобразованную в значение типа double. -(tloat) floatValue Возвращает строку, преобразованную в значение с плавающей точкой. -(NSInteger) integerValue Возвращает строку, преобразованную в целое значение NSInteger. -(int) intValue Возвращает строку, преобразованную в целое значение.

Методы, которые приводятся в таблице 15.3, создают или модифицируют объекты класса NSMutableString.

Табл. 15.3. Наиболее распространенные методы класса NSMutableString Метод Описание +(id) stringWithCapacity: size Создает строку, содержащую первоначально size символов. -(id) initWithCapacity: size Инициализирует строку с начальной длиной size символов. -(void) setstring: nsstring Присваивает строке nsstring. -(void) appendString: nsstring Добавляет nsstring в конец строки-получателя. -(void) deleteCharactersInFtange: range Удаляет символы в указанном диапазоне. -(void) insertstring; nstring atlndex: i Выполняет вставку nsstring в строку-получатель, начиная с индекса i. -(void) replaceCharactersInRange: range withString: nsstring Выполняет замену символов в указанном диапазоне на nsstring. -(void) replaceOccurrencesOfString: nsstring withString: nsstring2 options: opts range: range Выполняет замену всех экземпляров nsstring на nsstring2 в указанном диапазоне и в соответствии с опциями opts. Опции могут представлять побитовую OR-комбинацию NSBackwardsSearch (поиск начинается с конца диапазона), NSAnchoredSearch (совпадение nsstring должно быть только с начала диапазона), NSUteraiSearch (выполняется побайтовое сравнение) и NSCaselnsensitiveSearch.

Объекты класса NSString широко используются в этой книге. Для разбора арок на маркеры нужно рассмотреть класс Foundation NSScanner. 15.3. Объекты-массивы

Массив в Foundation – это упорядоченный набор объектов. Чаще всего (но не обязательно) элементы массива имеют один определенный тип. Аналогично мутабельным и немутабсльным строкам, существуют мутабельные и немута– бельные массивы. Для работы с немутабельными (immutable) массивами исполь-зуется класс NSArray; для мутабельных (mutable) массивов используется класс NSMutableArray. Последний класс является подклассом предыдущего и наследует его методы. Для работы с объектам и-массивам и в программах нужно включить строку #import

В программе 15.6 задастся массив для хранения названий месяцев, а затем выводятся названия месяцев. #import #import #import #import int main (int argc, char *argv[]) { int i; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Создание массива, содержащего названия месяцев NSArray *monthNames = [NSArray arrayWithObjects: @"January", @"February", @"March", @"April", @"May", @"June", @"July'', @"August", @"September", @"October", @"November", @"December", nil ]; // Теперь вывод всех элементов этого массива NSLog (@"Month Name"); NSLog (@"===== ===="); for (i = 0; i < 12; ++i) NSLog (@" %2i %@", i + 1, [monthNames objectAtlndex: i]); [pool drain]; return 0; }

Вывод программы 15.6 Month Name 1 January 2 February 3 March 4 April 5 May 6 June 7 July 8 August 9 September 10 October 11 November 12 December

Метод этого класса arrayWithObjects: создает массив со списком объектов в виде его элементов. Объекты перечисляются по порядку и разделяются запятыми. Это специальный синтаксис методов, которые принимают переменное число аргументов. Чтобы закончить список, нужно поставить nil в качестве последнего значения списка (nil не сохраняется внутри массива).

В программе 15.7 массиву monthNames присваиваются 12 строковых значений в виде аргументов для метода arrayWithObjects:.

Элементы массива идентифицируются своим индексом (порядковым номе-ром). Аналогично объектам класса NSString, индексирование начинается с нуля, поэтому массив, содержащий 12 элементов, имеет допустимые индексы 0-11. Метод objectAdndex: считывает элемент массива но его индексу.

В этой программе каждый элемент из массива считывается с помощью метода objectAUndex: в цикле for. Каждый считываемый элемент выводится с помощью NSLog.

В программе 15.7 создается таблица простых (prime) чисел. Поскольку про-стые числа добавляются в массив по мере их создания, здесь требуется мута– бельный массив. Память для объекта primes класса NSMutableArray выделяется с помощью метода arrayWithCapacity:. Указанный аргумент 20 задаст начальный размер массива; размер мутабельного массива автоматически увеличивается во время выполнения программы.

Хотя простые числа являются целыми, мы не можем сохранять значения типа int внутри этого массива. Данный массив может содержать только объекты, поэтому нам нужно сохранять в массиве primes целые объекты класса NSNumber. #import #import #import #import #import #define MAXPRIME 50 int main (int argc, char *argv[]) { int i, p, prevPrime; BOOL isPrime; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Создание массива для хранения простых чисел NSMutableArray *primes = [NSMutableArray arrayWithCapacity: 20]; // Сохранение в массиве первых двух простых чисел (2 и 3) [primes addObject: [NSNumber numberWithlnteger: 2]]; [primes addObject: [NSNumber numberWithlnteger: 3]]; // Вычисление остальных простых чисел for (р = 5; р <= MAXPRIME; р += 2) { // проверяется, что р – простое число isPrime = YES; i = 1; do { prevPrime = [[primes objectAtlndex: i] integerValue]; if (p % prevPrime == 0) isPrime = NO; ++i; } while (isPrime == YES && p / prevPrime >= prevPrime); if (isPrime) [primes addObject: [NSNumber numberWithlnteger: p]]; } // Вывод результатов for (i = 0; i < [primes count]; ++i) NSLog (@"%li", (long) [[primes objectAtlndex: i] integerValue]); [pool drain]; return 0; }

Вывод программы 15.7 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

kMaxPrime определяется как максимальное простое число для вычислений (в данном случае 50).

После выделения памяти для массива primes задаются два первых элемента массива с помощью следующих операторов. [primes addObject: [NSNumber numberWithlnteger: 2]]; [primes addObject: [NSNumber numberWithlnteger: 3]];

Метод addObject: добавляет объект в коней массива. В данном случае добав-ляются объекты класса NSNumber, создаваемые соответственно из целых значе-ний 2 и 3.

Затем в программе начинается цикл for для поиска простых чисел, начиная с 5, вплоть до kMaxPrime с пропуском промежуточных четных чисел (р += 2).

Для каждого возможного числа р проверяется его делимость на предыдущие простые числа. В случае делимости р не является простым числом. Для ускорения мы проверяем делимость только на простые числа, не превышающие квадратный корень из р. Дело в том, что если число не является простым, оно должно делиться на простое число, которое не больше его квадратного корня. Поэтому выражение р / prevPrime >= prevPrime

верно, earn prevPrime меньше, чем квадратный корень из р.

Если при выходе из цикла do-while флаг isPrime по-прежнему равен YES, зна-чит, мы нашли еще одно простое число. В этом случае р добавляется в массив primes, и выполнение программы продолжается.

Краткое замечание по эффективности. Классы Foundation очень удобны для работы с массивами, однако при работе с большими массивами чисел и сложными алгоритмами нужно научиться выполнять такие задачи с помощью низ-коуровневых конструкций языка для массивов, которые могут оказаться более эффективными сточки зрения использования памяти и скорости выполнения. См. раздел «Массивы» в главе 13. Создание адресной книги

Рассмотрим пример создания адресной книги. Она будет содержать адресные карточки. Для упрощения эти адресные карточки будут содержать только имя человека и его адрес электронной почты. Можно легко расширить эти данные, добавив другую информацию, например, почтовый адрес и номер телефона, но мы оставляем это вам как упражнение в конце главы. Создание адресной карточки

Мы начинаем с определения нового класса AddressCard. Нам нужны средства для создания новой адресной карточки, задания ее полей имени (паше) и электронной почты (email), чтения этих полей и вывода каргочки. В графической среде можно было бы использовать некоторые удобные процедуры, например, из фреймворка Application Kit, чтобы рисовать карточку на экране.

В программе 15.8 показан файл секции interface для нового класса AddressCard. Мы не будем пока синтезировать методы доступа (accessor methods); мы напишем их сами в качестве упражнения. #import #import @interface AddressCard: NSObject { NSString *name; NSString *email; } -(void) setName: (NSString *) theName; -(void) setEmail: (NSString *) IheEmail; -(NSString *) name; -(NSString *) email; -(void) print; @end

Это легко сделать с помощью файла секции implementation программы 15.8. #import "AddressCard.h" @implementation AddressCard -(void) setName: (NSString *) theName { name = [[NSString alloc] initWithString: theName]; } -(void) setEmail: (NSString *) theEmail { email = [[NSString alloc] initWithString: theEmail]; } -(NSString *) name { return name; } -(NSString *) email { return email; } -(void) print { NS Log (@"===================================="); NSLog (@"| Г); NSLog (@"| %-31s |", Iname UIE8String]); NSLog (@"| %-31s j", [email UTF8String]); NSLog (@"| I"); NSLog (@"| Г); NSLog (@"| Г); NSLog (@"| О О Г); NSLog (@"===================================="); } @end

Можно было бы сделать так, чтобы методы setName: и setEmail: сохраняли объекты непосредственно в своих переменных экземпляра с помощью следующих определений методов. -(void) setName: (NSString *) theName { name = theName; } -(void) setEmail: (NSString *) theEmail { email = theEmail; }

Но тогда объект класса AddressCard не будет владеть своими объектами-чле-нами. Мы уже говорили в главе 8 о получении объектом владения применительно к классу Rectangle, владеющему своим объектом origin.

Определение этих методов следующим способом тоже неверно, поскольку методы AddressCard тоже не будут владеть своими объектами name и email – ими будет владеть NSString. -(void) setName: (NSString *) theName { name = [NSString stringWithString: theName]; } -(void) setEmail: (NSString *) theEmail { email = (NSString stringWithString: theEmail]; }

Вернемся к программе 15.8. Метод print представляет пользователя в виде адресной карточки в формате, напоминающем карточку Rolodex (они исполь-зовались в картотеках). Символы %-31s при вызове NSLog указывают вывод в виде С-строки UTF8 при ширине поля 31 символ с выравниванием полевому краю. Так пользователь сможет брать карточку за правый край.

После создания класса AddressCard мы можем написать тестовую программу для создания адресной карточки, задания ее значений и ее вывода (см. программу 15.8). #import "AddressCard.h" #import int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *aName = @ "Julia Kochan"; NSString *aEmail = @"jewls337(9>axlc.comn; AddressCard *card1 = [[AddressCard alloc] init]; [cardl setName: aName]; [card 1 setEmail: aEmail]; [cardl print]; [cardl release]; [pool drain]; return 0; }

Вывод программы 15.8 ======================================== | | | Julia Kochan | | [email protected] | | | | | | | | O O | ========================================

В этой программе строка [cardl release]; применяется для освобождения памяти, которая занята адресной карточкой. Из предыдущих глав вы должны понимать, что высвобождение объекта класса AddressCard таким способом не приводит к освобождению памяти, которую мы выделили для его членов name и email. Чтобы избежать утечки памяти для класса AddressCard, нужно заместить метод dealloc, высвобождая эти члены при освобож-дении памяти для объекта AddressCard. Ниже приводится замещающий метод dealloc для класса AddressCard. -(void) dealloc { [name release]; [email release]; [super dealloc]; }

Метод dealloc должен высвобождать свои собственные переменные экземп-ляра до использования super для ликвидации самого объекта. Объект становится недействительным после того, как освобождена память объекта (dealloc).

Чтобы избежать утечки памяти для класса AddressCard, нужно также внести изменения в методы setName: и setEmail: и освобождать память, которая исполь-зуется объектами, сохраненными в их переменных экземпляра. Если кто-то изменяет имя на карточке, мы должны освободи ть память, которая используется старым именем, прежде чем заменить его новым именем. Дцля адреса элек– тронной почты мы тоже должны освободить память, которая используется для этого адреса, прежде чем заменить его новым.

Ниже приводятся новые методы setName: и setEmail: для класса, который пра-вильно управляет памятью. -(void) setName: (NSString *) theName { [name release]; name = [[NSString alloc] initWithString: theName]; } -(void) setEmail: (NSString *) theEmail { [email release]; email = [[NSString alloc] initWithString: theEmail]; }

Мы можем отправлять сообщение nil-объекту; поэтому выражения с сооб-щениями [name release];

и [email release];

допустимы, даже если name или email не были заданы ранее. Синтезируемые методы AddressCard

Теперь, когда описан подходящий способ написания методов доступа setName: и setEmail:, мы можем вернуться к началу и позволить самой системе сгенерировать методы доступа (accessor method). Рассмотрим второй вариант файла секции interface AddressCard. #import #import @interface AddressCard: NSObject { NSString *name; NSString *email; } @property (copy, nonatomic) NSString *name, *email; -(void) print; @end

В строке @property (copy, nonatomic) NSString *name, *email;

содержатся атрибуты сору и nonatomic для свойств (property). Атрибут сору указывает, что нужно создать копию переменной экземпляра в ее методе-установши– ке (setter), как мы делали в предыдущей версии. Действие по умолчанию – не создавать копию, а просто выполнить присваивание (атрибут по умолчанию assign), что является неверным подходом, как мы выяснили выше.

Атрибут nonatomic указывает, что метод-получатель (getter) не должен удер-живать (retain) или автоматически высвобождать (autorelease) переменную экземпляра, прежде чем возвратить ее значение. В главе 18 эта тема описывается более подробно.

Программа 15.9 – это новый файл секции implementation AddressCard, кото-рый указывает, что методы доступа будут синтезированы. #import "AddressCard.h" @implementation AddressCard @synthesize name, email; -(void) print { NSLog (@"============================="); NSLog (@"| |"); NSLog (@"| %-31s |", [name UTF8String]}; NSLog (@"| %-31s |", [email KTF8String]); NSLog (@"| |"); NSLog (@"| |"); NSLog (@"| |"); NSLog (@"| O O |"); NSLog (@"============================="); } @end

Мы оставляем вам в качестве упражнения проверку того, что это новое оп-ределение AddressCard с синтезируемыми методами доступа работает с тестовой программой, показанной в программе 15.9.

Теперь добавим еше один метод в класс AddressCard. Предположим, что мы хотим задавать поля name и email с помощью одного вызова. Чтобы сделать это, мы добавим новый метод setName:andEmail:. Он имеет следующий вид. -(void) setName: (NSString *) theName andEmail: (NSString *) theEmail { self.name = theName; self.email = theEmail; }

Полагаясь на синтезируемые методы-установщики для задания соответству-ющих переменных экземпляра (вместо их непосредственного задания внутри самого метода), мы повышаем уровень абстрагирования, делая программу более независимой от внутренних структур данных. Мы также используем свойства синтезируемого метода; в данном случае это копирование (сору) вместо присваивания (assign) значения переменной экземпляра.

Этот метод тестируется в программе 15.9. #import #import "AddressCard.h" int main {int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *aName = @ "Julia Kochan"; NSString *aEmail = @"[email protected]"; NSString *bName = @"Tony lannino"; NSString *bEmail = @"[email protected]"; AddressCard *card1 = [[AddressCard alloc] init]; AddressCard *card2 = [[AddressCard alloc] init]; [cardl setName: aName andEmail: aEmail]; [card2 setName: bName andEmail: bEmail]; [cardl print]; [card2 print]; [cardl release]; [card2 release]; [pool drain]; return 0; }

Вывод программы 15.9 ======================================== | | | Julia Kochan | | [email protected] | | | | | | | | O O | ======================================== ======================================== | | | Tony lannino | | [email protected] | | | | | | | | O O | ========================================

Класс AddressCard, казалось бы, действует правильно. Но как быть, если нужно работать с большим числом адресных карточек (объектов AddressCard)? Видимо, имеет смысл собрать их вместе. Именно это мы и сделаем, определив новый класс AddressBook (Адресная книга). В классе AddressBook будет храниться имя адресной книги и набор адресных карточек в объекте-массиве. Начнем со средств создания новой адресной книги, добавления в нее новых адресных карточек, определения числа содержащихся в ней записей и вывода списка ее содержимого. Затем нам потребуются средства поиска в этой адресной книге, удаления записей, редактирования существующих записей, их сортировки и создания копии содержимого.

Начнем с простого файла секции interface (программа 15.10). #import #import "AddressCard.h" @interface AddressBook: NSObject { NSString *bookName; NSMutableArray *book; } -(id) initWithName: (NSString *) name; -(void) addCard: (AddressCard*) theCard; -(int) entries; -(void) list; -(void) dealloc; @end

Метод initWithName: создает начальный массив для адресных карточек и со-храняет имя адресной книги. Метод addCard: добавляет отдельную адресную карточку (AddressCard) в книгу. Метод entries возвращает число адресных карточек в книге, а метод list выводит краткий список всего содержимого книги. В программе 15.10 показан файл секции implementation для класса AddressBook. #import "AddressBook.h" @Implementation AddressBook; // задание имени адресной книги и пустой книги -(id) initWithName: (NSString *) name { self = [super init]; if (self) { bookName = [[NSString alloc] initWithString: name]; book = [[NSMutableArray alloc] init]; } return self; } -(void) addCard: (AddressCard *) theCard { [book addObject: theCard]; } -(int) entries { return [book count]; } -(void) list { NSLog (@"======== Contents of: %@ =========", bookName); for (AddressCard *theCard in book ) NSLog (@"%-20s %-32s' [theCard.name UTF8String], [theCard.email UTF8String]); NSLog (@"============================================="); } -(void) dealloc { [bookName release]; [book release]; [super dealloc]; } @end

Метод initWithName: сначала вызывает метод init для суперкласса, чтобы вы-полнить его инициализацию. Затем он создает строковый объект (с использо-ванием alloc, то есть он владеет им) и присваивает ему имя адресной книги, пе-реданное как name. После этого выполняется выделение памяти и инициализация пустого мутабельного массива, который сохраняется в переменной экземпляра book.

Как мы определили, метод initWithName: возвращает обьект типа id, а не объект AddressBook. Если класс Address Book имеет подкласс, то аргумент для initWithName: не является объектом AddressBook; его тип определяется подклассом. Поэтому мы определяем тип возвращаемого объекта как обобщенный тип объекта.

Отметим также, что в initWithName: мы получаем владение переменными эк-земпляра bookName и book с помощью alloc. Например, если создать массив для book с помощью метода NSMutableArray array, как в book = [NSMutableArray array];

вы все же не будете владельцем массива book; им будет владеть NSMutabbArray. Таким образом, вы не сможете освободить его память, когда будете освобождать память для объекта AddressBook.

Метод addCard: принимает в качестве аргумента объект AddessCard и добавляет его в адресную книгу.

Метод count выдает число элементов массива. Метод entries использует эго значение, возвращая число адресных карточек, хранящихся в адресной книге. Быстрое перечисление

В цикле for метода list показана новая конструкция. for ( AddressCard *theCard in book) NSLog {@"%-20s %-32s", [theCard.name UTFBString], [theCard.email UTF8String]);

Здесь применяется метод под названием быстрое перечисление (fast enumeration), который осуществляет перебор всех элемен шв массива book. У него простой синтаксис: определяется переменная, которая содержит по очереди каждый элемент массива (AddressCard *theCard). После ключевого слова in указывается имя массива. При выполнении цикла for указанной переменной сначала присваивается первый элемент массива, а затем выполняется тело цикла. На следующем шаге цикла этой переменной присваивается агорой элемент мас-сива и выполняется тело цикла. Цикл выполняется до тех пор, пока переменной не будут присвоены все элементы массива (каждый раз с выполнением тела цикла).

Если бы мы определили ранее theCard как объект AddressCard, то цикл for выг-лядел бы проще: for (theCard in book)

Ниже приводится тестовая программа 15.10 для проверки нового класса AddressBook. #import "AddressBook.h" #import int main {int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePooi alloc] init]; NSString *aName = @"Julia Kochan"; NSString *aEmail = @"[email protected]"; NSString *bName = @'Tony lannino"; NSString *bEmail = @"tony. [email protected]''; NSString *cName = @''Stephen Kochan"; NSString *cEmail = @"[email protected]"; NSString *dName = @"Jamie Baker"; NSString *dEmail = @"[email protected]"; AddressCard *card1 = [[AddressCard alloc] init]; AddressCard *card2 = [[AddressCard alloc] init]; AddressCard *card3 = [[AddressCard alloc] init]; AddressCard *card4 = [[AddressCard alloc] init]; AddressBook *myBook = [AddressBook alloc]; // Сначала задаем четыре адресные карточки [card1 setName: aName andEmail: aEmail]; [card2 setName: bName andEmail: bEmail]; [card3 setName: cNarne andEmail: cEmail]; [card4 setName: dName andEmail: dEmail]; // Теперь инициализируем адресную книгу myBook = [myBook initWithName: @"Linda’s Address Book"]; NSLog (@"Entries in address book after creation: %i", [myBook entries]); // Добавляем несколько карточек в адресную книгу [myBook addCard: cardl]; [myBook addCard: card2]; [myBook addCard: card3]; [myBook addCard: card4];  NSLog(@"Entries in address book after adding cards: %i", [myBook entries]); // Теперь вывод всех записей адресной книги [myBook list]; [cardl release]; [card2 release]; [card3 release]; [card4 release]; [myBook release]; [pool drain]; return 0; }


    Ваша оценка произведения:

Популярные книги за неделю