Вчера мучался в догадках, почему под одной и той же ячейкой в UITableView (одна ячейка в одной группе, стиль выбран UITableViewStyleGrouped) появлялась одна и та же горизонтальная полосочка. Баг был явно привязан именно к этой ячейке.
Оказалось, что я задавал высоту ячейки не как целое или округлённое до целого число (то есть возвращал из метода heightForRowAtIndexPath значение с заметной на экране дробной частью).
четверг, 15 декабря 2011 г.
среда, 2 ноября 2011 г.
Как собирать проекты с гигантскими функциями
Случается так, что гигантские функции (в несколько тысяч строк кода) не позволяют собрать проект. Если нет ошибок компиляции, но есть непонятная ошибка линковки, то попробуйте в свойствах Xcode-проекта убрать галочку с пункта GCC 4.2 Code Generation -> Compile for Thumb. Мне это помогло (нашёл совет где-то в англоязычных сайтах).
Ярлыки:
большая,
гигантская,
компиляция,
линковка,
настройка,
ошибка,
функция,
xcode
понедельник, 31 октября 2011 г.
Мои скрипты для работы в Xcode
Вот какие скрипты я использую для работы в Xcode (на них можно назначать сочетания клавиш). Для добавления скриптов и назначения им сочетаний клавиш найдите в полосе меню (у меня Xcode 3) пункт, напоминающий свиток, а в нём субменю Edit user scripts...
В ОСНОВНОМ ЭТО СКРИПТЫ ДЛЯ ДОБАВЛЕНИЯ ЧАСТО ИСПОЛЬЗУЕМЫХ СТРОК (без горячих сочетаний клавиш теряется их неоценимая помощь в работе):
1) Добавление NSLocalizedString(@"", @"")
#!/bin/sh
echo "NSLocalizedString(@\"\", @\"\")"
2) Добавление // property
#!/bin/sh
echo "// property"
3) и так далее до пункта 11)
#!/bin/sh
echo "@property (nonatomic, retain) IBOutlet "
4)
#!/bin/sh
echo "//----------------------------------------------------------"
5)
#!/bin/sh
echo "////////////////////////////////////////////////////////////"
6)
#!/bin/sh
echo "NSLog(@\"\");"
7)
#!/bin/sh
echo "NSLog(@\"%s function %s \", __FILE__, __FUNCTION__);"
8)
#!/bin/sh
echo "NSLog(@\"%s line %d \", __FILE__, __LINE__);"
9)
#!/bin/sh
echo "using namespace "
10)
#!/bin/sh
echo "@synthesize "
11) Вставляю свои инициалы, дату и время (чтобы не забыть удалить после экспериментов)
#!/bin/sh
echo "//MD:$(date +%Y%m%d-%H:%M)"
12)
#!/bin/sh
echo "////////////////////////////////////////////////////////////"
echo "#pragma mark -"
echo "#pragma mark methods"
echo "////////////////////////////////////////////////////////////"
13) Сначала выделяете нужный текст (например имя функции). После выполнения этого скрипта у вас получится в коде вывод в отладочную консоль выделенного текста.
#!/bin/sh
echo "NSLog(@\"%%%{PBXSelectedText}%%%\");";
В ОСНОВНОМ ЭТО СКРИПТЫ ДЛЯ ДОБАВЛЕНИЯ ЧАСТО ИСПОЛЬЗУЕМЫХ СТРОК (без горячих сочетаний клавиш теряется их неоценимая помощь в работе):
1) Добавление NSLocalizedString(@"", @"")
#!/bin/sh
echo "NSLocalizedString(@\"\", @\"\")"
2) Добавление // property
#!/bin/sh
echo "// property"
3) и так далее до пункта 11)
#!/bin/sh
echo "@property (nonatomic, retain) IBOutlet "
4)
#!/bin/sh
echo "//----------------------------------------------------------"
5)
#!/bin/sh
echo "////////////////////////////////////////////////////////////"
6)
#!/bin/sh
echo "NSLog(@\"\");"
7)
#!/bin/sh
echo "NSLog(@\"%s function %s \", __FILE__, __FUNCTION__);"
8)
#!/bin/sh
echo "NSLog(@\"%s line %d \", __FILE__, __LINE__);"
9)
#!/bin/sh
echo "using namespace "
10)
#!/bin/sh
echo "@synthesize "
11) Вставляю свои инициалы, дату и время (чтобы не забыть удалить после экспериментов)
#!/bin/sh
echo "//MD:$(date +%Y%m%d-%H:%M)"
12)
#!/bin/sh
echo "////////////////////////////////////////////////////////////"
echo "#pragma mark -"
echo "#pragma mark methods"
echo "////////////////////////////////////////////////////////////"
13) Сначала выделяете нужный текст (например имя функции). После выполнения этого скрипта у вас получится в коде вывод в отладочную консоль выделенного текста.
#!/bin/sh
echo "NSLog(@\"%%%{PBXSelectedText}%%%\");";
вторник, 18 октября 2011 г.
Новый Xcode 4.2 меня разочаровал
Новый Xcode 4.2 меня разочаровал примерно в том же отношении, как меня лет 10 тому назад основательно разочаровал Windows 98 (тогда приходилось как минимум каждый час нажимать кнопку Reset). Тогда я всерьёз решил перейти на Linux (хотя Линукс имхо хорошо подходит для людей, готовых в любой момент серьёзно заниматься именно Линуксом, то есть Линукс - это не инструмент для решения таких задач, где можно забыть про инструмент и решать задачи, а Линукс - это инструмент для овладения инструмента под названием Линукс. Но это моё мнение).
Так вот, Xcode 4.2 постоянно преподносит мне какие-то сюрпризы... Совершенно запутанные и нелогичные. Я уже втайне начал мечтать заняться по работе другой темой в программировании.
Сейчас истратил полчаса, из-за того, что Xcode утверждал мне о том, что невозможно использовать StoryBoard в IOS 4.3 и более ранних, хотя я многократно переключал DeploymentTarget в IOS 5.0. Оказывается, кроме моих действий (Clean не помогает) нужно ещё и поменять хотя бы что-то в исходниках, и снова сбилдить приложение. Жопа, жопа, жопа...
Много ещё и других глюков (столько глюков сразу в Xcode не было ни разу, хотя в этой новой версии много хороших задумок). Неужели после того, как Apple осталась без Стива Джобса, эта компания обречена потерять лидерские позиции? Я думаю, что очень даже может быть. Любое могущество основано на могуществе личности (это я прочитал у Наполеона Хилла).
Так вот, Xcode 4.2 постоянно преподносит мне какие-то сюрпризы... Совершенно запутанные и нелогичные. Я уже втайне начал мечтать заняться по работе другой темой в программировании.
Сейчас истратил полчаса, из-за того, что Xcode утверждал мне о том, что невозможно использовать StoryBoard в IOS 4.3 и более ранних, хотя я многократно переключал DeploymentTarget в IOS 5.0. Оказывается, кроме моих действий (Clean не помогает) нужно ещё и поменять хотя бы что-то в исходниках, и снова сбилдить приложение. Жопа, жопа, жопа...
Много ещё и других глюков (столько глюков сразу в Xcode не было ни разу, хотя в этой новой версии много хороших задумок). Неужели после того, как Apple осталась без Стива Джобса, эта компания обречена потерять лидерские позиции? Я думаю, что очень даже может быть. Любое могущество основано на могуществе личности (это я прочитал у Наполеона Хилла).
четверг, 6 октября 2011 г.
Функция поворота CGImage
Материал взят из http://connordenman.wordpress.com/2010/09/18/rotation-of-cgimage-iphoneipad-improved/
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
{
CGFloat angleInRadians = angle * (M_PI / 180);
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect imgRect = CGRectMake(0, 0, width, height);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL,
rotatedRect.size.width,
rotatedRect.size.height,
8,
0,
colorSpace,
kCGImageAlphaPremultipliedFirst);
CGContextSetAllowsAntialiasing(bmContext, YES);
CGContextSetInterpolationQuality(bmContext, kCGInterpolationHigh);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(bmContext,
+(rotatedRect.size.width/2),
+(rotatedRect.size.height/2));
CGContextRotateCTM(bmContext, angleInRadians);
CGContextDrawImage(bmContext, CGRectMake(-width/2, -height/2, width, height),
imgRef);
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
CFRelease(bmContext);
[(id)rotatedImage autorelease];
return rotatedImage;
}
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
{
CGFloat angleInRadians = angle * (M_PI / 180);
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect imgRect = CGRectMake(0, 0, width, height);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL,
rotatedRect.size.width,
rotatedRect.size.height,
8,
0,
colorSpace,
kCGImageAlphaPremultipliedFirst);
CGContextSetAllowsAntialiasing(bmContext, YES);
CGContextSetInterpolationQuality(bmContext, kCGInterpolationHigh);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(bmContext,
+(rotatedRect.size.width/2),
+(rotatedRect.size.height/2));
CGContextRotateCTM(bmContext, angleInRadians);
CGContextDrawImage(bmContext, CGRectMake(-width/2, -height/2, width, height),
imgRef);
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
CFRelease(bmContext);
[(id)rotatedImage autorelease];
return rotatedImage;
}
среда, 5 октября 2011 г.
Сохранение UIImage в png или jpeg файл
Материал взят из http://iphonedevelopertips.com/data-file-management/save-uiimage-object-as-a-png-or-jpeg-file.html
// Create paths to output images
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Test.png"];
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Test.jpg"];
// Write a UIImage to JPEG with minimum compression (best quality)
// The value 'image' must be a UIImage object
// The value '1.0' represents image compression quality as value from 0.0 to 1.0
[UIImageJPEGRepresentation(image, 1.0) writeToFile:jpgPath atomically:YES];
// Write image to PNG
[UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
// Let's check to see if files were successfully written...
// Create file manager
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
// Write out the contents of home directory to console
NSLog(@"Documents directory: %@", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
воскресенье, 2 октября 2011 г.
Проверка валидности email
- (BOOL) validateEmail: (NSString *) candidate
{
NSString *emailRegex = @ "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2, 4} ";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@ "SELF MATCHES %@ ", emailRegex];
return [emailTest evaluateWithObject:candidate];
}
Код взят из http://stackoverflow.com/questions/800123/best-practices-for -validating-email-address-in-objective-c-on-ios-2-0
{
NSString *emailRegex = @ "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2, 4} ";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@ "SELF MATCHES %@ ", emailRegex];
return [emailTest evaluateWithObject:candidate];
}
Код взят из http://stackoverflow.com/questions/800123/best-practices-for -validating-email-address-in-objective-c-on-ios-2-0
воскресенье, 18 сентября 2011 г.
Регулярные выражения для поиска в исходниках Xcode-проекта
[^//][^ ]NSLog - это регулярное выражение для поиска всех незакомментированных NSLog (лично я люблю выводить в лог всяческие значения и прочую лабуду, которая помогает мне понять, что вообще происходит в программе, не всегда это можно сделать только с одними брекпоинтами).
[^a-zA-Z_]id[^a-zA-Z_] - это регулярное выражение для поиска всех id, где справа и слева нет букв и нет знаков подчёркивания (может пригодиться, если вам нужно заменить тысячи локальных переменных или мемберов в тех коллективных исходниках, которые писали те плюсовые программисты, которые не знали или забыли (а у вас не хватает наглости их упрекать за повторяющуюся забывчивость), что в Obj-С id является именем типа (псевдоним типа NSObject*). Внимание! Квадратные скобки дают нам по одному символу слева и справа от id, которые не являются буквами и знаком подчёркивания. То есть поиск нам выдаст в числе прочих и всё 4 буквенные строки, где в центре каждой строки мы имеем id.
Поэтому, если вам нужно заменять в коллективных Си++ исходниках id на _id (ведь id является типом данных в Objective C, а ваши cpp файлы наверняка будут настроены в дереве проекта как cpp.objcpp файлы), то лучше сделайте так:
Вставьте в поле Find:
([^a-zA-Z_])id([^a-zA-Z_])
Вставьте в поле Replace:
\1_id\2
Дело в том, что в квадратных скобках мы имеем по одному символу (который не буква и не знак подчёркивания). Поэтому, при замене (если не использовать круглые скобки и в поле Replace просто написать _id) мы бы заменяли не только id, но и символ справа и символ слева от id, то есть съедались бы точки с запятой и прочие важные символы. \1 и \2 заставляет Xcode кроме _id вставить одиночные символы слева и справа (те, которые были слева и справа от оригинальной id).
[^a-zA-Z_]id[^a-zA-Z_] - это регулярное выражение для поиска всех id, где справа и слева нет букв и нет знаков подчёркивания (может пригодиться, если вам нужно заменить тысячи локальных переменных или мемберов в тех коллективных исходниках, которые писали те плюсовые программисты, которые не знали или забыли (а у вас не хватает наглости их упрекать за повторяющуюся забывчивость), что в Obj-С id является именем типа (псевдоним типа NSObject*). Внимание! Квадратные скобки дают нам по одному символу слева и справа от id, которые не являются буквами и знаком подчёркивания. То есть поиск нам выдаст в числе прочих и всё 4 буквенные строки, где в центре каждой строки мы имеем id.
Поэтому, если вам нужно заменять в коллективных Си++ исходниках id на _id (ведь id является типом данных в Objective C, а ваши cpp файлы наверняка будут настроены в дереве проекта как cpp.objcpp файлы), то лучше сделайте так:
Вставьте в поле Find:
([^a-zA-Z_])id([^a-zA-Z_])
Вставьте в поле Replace:
\1_id\2
Дело в том, что в квадратных скобках мы имеем по одному символу (который не буква и не знак подчёркивания). Поэтому, при замене (если не использовать круглые скобки и в поле Replace просто написать _id) мы бы заменяли не только id, но и символ справа и символ слева от id, то есть съедались бы точки с запятой и прочие важные символы. \1 и \2 заставляет Xcode кроме _id вставить одиночные символы слева и справа (те, которые были слева и справа от оригинальной id).
Ярлыки:
регулярные выражения,
regex,
regular expressions,
xcode
четверг, 15 сентября 2011 г.
Невозможно добавить исходник в дерево проекта?
Иногда бывает невозможно добавить существующий исходник в дерево проекта обычным способом (исходник или вообще какой-либо иной файл обозначен серым цветом, как будто бы он уже был добавлен в дерево проекта)
Тогда просто откройте вне проекта рядом папку с исходником (или иным нужным файлом) и перетащите нужный исходник (или файл) в дерево проекта в нужную группу
Удивительно, это работает!
Тогда просто откройте вне проекта рядом папку с исходником (или иным нужным файлом) и перетащите нужный исходник (или файл) в дерево проекта в нужную группу
Удивительно, это работает!
четверг, 25 августа 2011 г.
Много умных мыслей для разработчиков
Я люблю читать на этом сайте различные умные мысли (от Славы Панкратова и Александра Орлова)
http://www.it4business.ru/
А ещё я обожаю читать Джоэла Спольски (прочитал его 2 книги на русском языке, но многое оттуда есть и на этом сайте)
http://russian.joelonsoftware.com/
http://www.it4business.ru/
А ещё я обожаю читать Джоэла Спольски (прочитал его 2 книги на русском языке, но многое оттуда есть и на этом сайте)
http://russian.joelonsoftware.com/
четверг, 18 августа 2011 г.
Полезные ссылки для iOS-программиста
Вот страницы, на которые я каждый день заглядываю и иногда общаюсь с участниками (если могу помочь советом):
http://www.rsdn.ru/forum/apple.os/
http://touchdev.ru/
http://habrahabr.ru/blogs/macosxdev/
http://www.rsdn.ru/forum/apple.os/
http://touchdev.ru/
http://habrahabr.ru/blogs/macosxdev/
Ярлыки:
гиперссылки,
обсуждение,
помощь,
программирование,
ссылки,
форум,
ios,
iphone
понедельник, 6 июня 2011 г.
Apple официально анонсировала iOS 5.0, Mac OS X 10.7 и сервис iCloud
Компания Apple сегодня открыла ежегодную конференцию WWDC, ориентированную на разработчиков и партнеров компании. По традиции, взятой на вооружение маркетологами Apple, журналистов, ждавших от компании новинок, здесь было едва ли не больше, чем основ... полный текст
Источник: Cybersecurity.ru
среда, 18 мая 2011 г.
C++ объекты как мемберы Objective C классов
Я намучался изрядно с плюсовыми объектами, которые объявлял как обычные мемберы Objective C классов. Проблема в том, что вы не можете быть уверены, когда будет вызван деструктор такого мембера в момент прекращения жизни Objective C объекта, и будет вообще ли вызван этот деструктор.
К счастью есть простоё и надёжное решение.
Используйте обычный указатель или std::auto_ptr. Теперь вы сможете контролировать момент вызова конструктора и момент вызова деструктора. Если вам нужно будет уничтожать C++ объект при уничтожении его владельца (Objective C объекта), то самое подходящее место для этого - метод dealloc (аналог деструктора в Objective C классах).
Как выяснилось, я не напрасно предпочёл в качестве мемберов использовать указатели вместо обычных объектов. На http://rsdn.ru/?/forum/apple.os/ мне помогли разобраться с этой ситуацией (привели цитату из официальной документации)
Objective-C classes cannot have instance variables of C++ classes that do not have a default constructor or that have one or more virtual methods, but pointers to C++ objects can be used as instance variables without restriction (allocate them with new in the -init method).
К счастью есть простоё и надёжное решение.
Используйте обычный указатель или std::auto_ptr. Теперь вы сможете контролировать момент вызова конструктора и момент вызова деструктора. Если вам нужно будет уничтожать C++ объект при уничтожении его владельца (Objective C объекта), то самое подходящее место для этого - метод dealloc (аналог деструктора в Objective C классах).
Как выяснилось, я не напрасно предпочёл в качестве мемберов использовать указатели вместо обычных объектов. На http://rsdn.ru/?/forum/apple.os/ мне помогли разобраться с этой ситуацией (привели цитату из официальной документации)
Objective-C classes cannot have instance variables of C++ classes that do not have a default constructor or that have one or more virtual methods, but pointers to C++ objects can be used as instance variables without restriction (allocate them with new in the -init method).
Ярлыки:
деструктор,
мембер,
член,
c++,
dealloc,
destructor,
member,
objective c
UIActivityIndicator не всегда работает!
В некоторых случаях UIActivityIndicator не всегда работает. С чем это связано, я до сих пор не знаю.
Выяснил вот что - если после запуска в основном потоке активити-индикатора программа в основном потоке ничего не делает (что само по себе редкость и вряд ли имеет смысл, ведь пользователю нужно дать знать, что дескать программа что-то будет делать, и что она не зависла, а занята выполнением работы), то в таком случае активити-индикатор работает исправно.
Если же программа занялась плотно какими-то задачами в основном потоке (кстати, согласно рекомендациям от Apple в iPhone ГУИ-контролы вообще лучше юзать в основном потоке, если я не ошибаюсь), то активити-индикатор может "не успеть" сделать какую-то подготовительную работу и тогда пользователь его не увидит. Но это лишь мои догадки.
Как я вышел из положения? Приходится программно запускать специально созданный для этого таймер на 1/10 долю секунды (этого времени индикатору хватает), после этого запускать активити-индикатор и просто ничего не делать до срабатывания таймера (то есть до срабатывания функции-обработчика таймера). Этой паузы хватит, чтобы активити-индикатор глотнул воздуха и начал работать. Как только сработает таймер через 1/10 секунды, то останавливайте таймер и запускайте в основном потоке нужные вам функции, это уже не помешает активити-индикатору продолжать показывать, что дескать дела в основном потоке идут.
Конечно, есть риск, что пользователь что-то успеет нажать за 1/10 секунды। Для этого можно перестраховаться с помощью булевой переменной (т.е. заблокировать обработчики нажатий на контролы, вернее выходить из функций обработчиков если эта переменная показывает, что сейчас как раз идёт та самая 1/10 доля секунды).
Добавлено через много месяцев: сейчас я вместо таймера использую более подходящий и простой вызов функции
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay
Смотрите подробнее в документации (эта функция способна вызвать нужный вам код в текущем потоке через нужное время, этого глотка времени хватает, чтобы активити-индикатор закрутился).
Кстати, вся эта статья относится не только к активити-индикаторам, но и многим другим контролам (которым необходим глоток воздуха для того, чтобы успеть отобразиться на экране).
Выяснил вот что - если после запуска в основном потоке активити-индикатора программа в основном потоке ничего не делает (что само по себе редкость и вряд ли имеет смысл, ведь пользователю нужно дать знать, что дескать программа что-то будет делать, и что она не зависла, а занята выполнением работы), то в таком случае активити-индикатор работает исправно.
Если же программа занялась плотно какими-то задачами в основном потоке (кстати, согласно рекомендациям от Apple в iPhone ГУИ-контролы вообще лучше юзать в основном потоке, если я не ошибаюсь), то активити-индикатор может "не успеть" сделать какую-то подготовительную работу и тогда пользователь его не увидит. Но это лишь мои догадки.
Как я вышел из положения? Приходится программно запускать специально созданный для этого таймер на 1/10 долю секунды (этого времени индикатору хватает), после этого запускать активити-индикатор и просто ничего не делать до срабатывания таймера (то есть до срабатывания функции-обработчика таймера). Этой паузы хватит, чтобы активити-индикатор глотнул воздуха и начал работать. Как только сработает таймер через 1/10 секунды, то останавливайте таймер и запускайте в основном потоке нужные вам функции, это уже не помешает активити-индикатору продолжать показывать, что дескать дела в основном потоке идут.
Конечно, есть риск, что пользователь что-то успеет нажать за 1/10 секунды। Для этого можно перестраховаться с помощью булевой переменной (т.е. заблокировать обработчики нажатий на контролы, вернее выходить из функций обработчиков если эта переменная показывает, что сейчас как раз идёт та самая 1/10 доля секунды).
Добавлено через много месяцев: сейчас я вместо таймера использую более подходящий и простой вызов функции
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay
Смотрите подробнее в документации (эта функция способна вызвать нужный вам код в текущем потоке через нужное время, этого глотка времени хватает, чтобы активити-индикатор закрутился).
Кстати, вся эта статья относится не только к активити-индикаторам, но и многим другим контролам (которым необходим глоток воздуха для того, чтобы успеть отобразиться на экране).
Ярлыки:
активити,
индикатор,
таймер,
nstimer,
uiactivityindicator
четверг, 17 марта 2011 г.
Стандартные размеры контролов
Материал взят из http://jdg.net/post/106465937/standard-iphone-element-sizes
Core Elements:
Carrier Status bar - 320x20
UIView - 320x460
UINavigationBar - 320x44
UITabBar - 320x49
UISearchBar - 320x44
UIToolBar - 320x44
Data Input:
UIPickerView - 320x216
UIDatePicker - 320x216
UIKeyboard - 320x216
Buttons:
UISegmentedControl - 320x44
UIButton xx37
Fields:
UITextField - xx37
UISwitch 94x27
UISlider - xx23
Indicators:
UIProgressView -xx9
UIActivityIndicatorView - 37x37
UIPageControl - 38x36
Ярлыки:
контрол,
ipad,
iphone,
iphone os,
iphone sdk,
ipod,
ipod touch
четверг, 10 февраля 2011 г.
Как сделать один общий проект для нескольких статических библиотек (либ)
Недавно я сумел таки обойти некоторые ограничения Xcode и сделать один общий проект для нескольких статических библиотек (либ).
Ограничения касаются прежде всего такого макроопределения как __IPHONE_3_1 (последние цифры не столь важны, это уже технические моменты - всё зависит от того, начиная с какой версии IOS ваше приложение и библиотеки должны работать).
Если для каждой либы (т.е. библиотеки) вы создаёте свой отдельный Xcode-проект, то в m и mm исходниках (а также в c/cpp - исходниках, если они в своих свойствах выставлены как c.objcpp и cpp.objcpp файлы) макроопределения __IPHONE_... срабатывают безотказно.
То есть вы можете в вашем коде сделать такую проверку:
#ifdef __IPHONE_3_1
sad;flkasjdf;laksjdfa;sldfkja;sdlkfjasd;lkfj; // всякая дрянь, которая не точно компилируется
#endif
Если компилятор будет ругаться на эту дрянь, то значит всё в порядке.
Проблема начинается, когда вы объединяете несколько либ в один проект (то есть для каждой либы добавляете в проект новый Target с указанием имени либы, а потом нужные для этой либы исходники указываете в свойствах как предназначенные именно для этого Target).
Можно искусственным способом заставить ваш проект узнавать макроопределение __IPHONE_3_1
Для этого зайдите в свойства проекта и найдите там раздел GCC 4.2 Preprocessing, а в этом разделе такую строку (слева) Preprocessor Macros. Так вот в поле справа можно добавить такую строку
__IPHONE_3_1=1
Туда же можно добавить и другие важные строки, например __GNUC__=1 или TARGET_OS_IPHONE=1
Если вы не найдёте такой раздел (это увы случается, и я пока не выяснил почему так бывает), то можете сделать по другому. Попробуйте ввести в поле поиска наверху строку GCC_PREPROCESSOR_DEFINITIONS - сразу же должно будет появиться внизу то, что нужно.
Ограничения касаются прежде всего такого макроопределения как __IPHONE_3_1 (последние цифры не столь важны, это уже технические моменты - всё зависит от того, начиная с какой версии IOS ваше приложение и библиотеки должны работать).
Если для каждой либы (т.е. библиотеки) вы создаёте свой отдельный Xcode-проект, то в m и mm исходниках (а также в c/cpp - исходниках, если они в своих свойствах выставлены как c.objcpp и cpp.objcpp файлы) макроопределения __IPHONE_... срабатывают безотказно.
То есть вы можете в вашем коде сделать такую проверку:
#ifdef __IPHONE_3_1
sad;flkasjdf;laksjdfa;sldfkja;sdlkfjasd;lkfj; // всякая дрянь, которая не точно компилируется
#endif
Если компилятор будет ругаться на эту дрянь, то значит всё в порядке.
Проблема начинается, когда вы объединяете несколько либ в один проект (то есть для каждой либы добавляете в проект новый Target с указанием имени либы, а потом нужные для этой либы исходники указываете в свойствах как предназначенные именно для этого Target).
Можно искусственным способом заставить ваш проект узнавать макроопределение __IPHONE_3_1
Для этого зайдите в свойства проекта и найдите там раздел GCC 4.2 Preprocessing, а в этом разделе такую строку (слева) Preprocessor Macros. Так вот в поле справа можно добавить такую строку
__IPHONE_3_1=1
Туда же можно добавить и другие важные строки, например __GNUC__=1 или TARGET_OS_IPHONE=1
Если вы не найдёте такой раздел (это увы случается, и я пока не выяснил почему так бывает), то можете сделать по другому. Попробуйте ввести в поле поиска наверху строку GCC_PREPROCESSOR_DEFINITIONS - сразу же должно будет появиться внизу то, что нужно.
среда, 26 января 2011 г.
Xcode vs Visual Studio
Я уже работаю полтора года разработчиком приложений для iPhone (используя единственную официальную среду разработки Xcode). За несколько лет до этого я несколько месяцев работал с Visual Studio.
Да, действительно чувствуется, что в Apple самые главные люди - дизайнеры, а не программисты. Microsoft проявляет больше заботы об удобстве работы программистов с их основным инструментом.
То есть я больше люблю Visual Studio, чем Xcode.
Да, действительно чувствуется, что в Apple самые главные люди - дизайнеры, а не программисты. Microsoft проявляет больше заботы об удобстве работы программистов с их основным инструментом.
То есть я больше люблю Visual Studio, чем Xcode.
Подписаться на:
Сообщения (Atom)