Чтение онлайн

ЖАНРЫ

Программирование на Objective-C 2.0
Шрифт:

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

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

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

Рассмотрим

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

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

В программе 15.8 показан файл секции interface для нового класса AddressCard. Мы не будем пока синтезировать методы доступа (accessor methods); мы напишем их сами в качестве упражнения. #import <Foundation/NSObject.h> #import <Foundation/NSString.h> @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 <Foundation/NSAutoreleasePool.h> 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 | | jewls337@axlc.com | | | | | | | | 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 <Foundation/NSObject.h> #import <Foundation/NSString.h> @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 эта тема описывается более подробно.

Поделиться с друзьями: