Как хранятся / извлекаются строковые константы в Objective-C? - PullRequest
7 голосов
/ 11 июля 2011

Может кто-нибудь объяснить, где и как строковые константы хранятся компилятором и как они доступны во время выполнения?

Ответы [ 2 ]

11 голосов
/ 11 июля 2011

Сначала обязательно: вам не должно быть дела до того, как это делает компилятор; все, что зависит от того, как компилятор делает это, представляет собой опасную зависимость от чего-то, что не гарантируется и может изменяться в зависимости от того, как компилятор оптимизирует. Не пишите код, основанный на этом. В самом деле. Хорошо, мы убрали это с дороги.

Скажем, у вас есть такой код:

NSString *something = @"I'm a constant";

Компилятор сгенерирует это:

    .section    __TEXT,__cstring,cstring_literals
l_.str:                                 ## @.str
    .asciz   "I'm a constant"

Как видите, он хранится в разделе __TEXT вместе с вашим кодом как литерал cstring. В __DATA она будет хранить саму константу CFString так:

    .section    __DATA,__cfstring
    .align  4                       ## @_unnamed_cfstring_
L__unnamed_cfstring_:
    .quad   ___CFConstantStringClassReference
    .long   1992                    ## 0x7c8
    .space  4
    .quad   l_.str
    .quad   14                      ## 0xe

Во-первых, он хранит CFType (CFConstantStringClassReference). Затем внутренняя информация о строке (является ли она неизменной, как она освобождается, является ли она юникодом и т. Д.), Указатель на строку cstring и длину (14). Если вам нужны подробности о структуре, откройте источники CF с opensource.apple.com и посмотрите на CFString.c. Это объясняет все поле «внутренней информации» довольно хорошо. (Извлеките их из Snow Leopard; Apple не публикует их как часть iOS, но они одинаковы.)

Вторая постоянная строка будет выглядеть следующим образом, просто чтобы продемонстрировать, как происходит присвоение имен символам для ассемблера.

    .section    __TEXT,__cstring,cstring_literals
l_.str2:                                ## @.str2
    .asciz   "%@"

    .section    __DATA,__cfstring
    .align  4                       ## @_unnamed_cfstring_3
L__unnamed_cfstring_3:
    .quad   ___CFConstantStringClassReference
    .long   1992                    ## 0x7c8
    .space  4
    .quad   l_.str2
    .quad   2                       ## 0x2

Если вы хотите лучше разобраться с этим, просто попросите Xcode сгенерировать сборку для простого файла и посмотреть, что он делает. О, и, конечно, вы никогда не должны использовать эту информацию, потому что gcc может измениться в любое время. Но это отличный материал, в который можно покопаться.

1 голос
/ 11 июля 2011

Вы должны создать заголовочный файл как

// Constants.h
extern NSString * const MyFirstConstant;
extern NSString * const MySecondConstant;
//etc.

Вы можете включить этот файл в каждый файл, который использует константы, или в предварительно скомпилированный заголовок проекта.

Вы определяете эти константы в файле .m как

// Constants.m
NSString * const MyFirstConstant = @"FirstConstant";
NSString * const MySecondConstant = @"SecondConstant";

Constants.m должен быть добавлен к цели вашего приложения / фреймворка, чтобы он был связан с конечным продуктом.

Преимущество использования строковых констант вместо #define d-констант состоит в том, что вы можете проверить равенство, используя сравнение указателей (stringInstance == MyFirstConstant), которое намного быстрее, чем сравнение строк ([stringInstance isEqualToString:MyFirstConstant])

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...