Очень важно, если вы решили часть рутинных операций возложить на такой удобный инструмент как Interface Builder не забывать об одном правиле. Каждый объект, который создаётся не динамически в коде (например smthObject = [[SmthClass alloc] initWith... ]), а создан с помощью Interface Builder, каждый такой объект должен иметь своего хозяина (разве что главный делегат приложения гарантированно работает по умолчанию).
То есть любой ваш объект (созданный с помощью Interface Builder) должен принадлежать кому-нибудь как IBOutlet-переменная. Я убеждался в этом уже много раз на практике. Иначе происходят падения программы при попытке заставить этот объект что-либо сделать, из-за того, что у этого объекта (если он не принадлежит никому как IBOutlet-переменная) например вызывается метод, а объект вроде не существует (раз ни к кому не принадлежит). Может быть гуру-программисты дадут более точное объяснение этому явлению...
То есть любой ваш объект (созданный с помощью Interface Builder) должен принадлежать кому-нибудь как IBOutlet-переменная. Я убеждался в этом уже много раз на практике. Иначе происходят падения программы при попытке заставить этот объект что-либо сделать, из-за того, что у этого объекта (если он не принадлежит никому как IBOutlet-переменная) например вызывается метод, а объект вроде не существует (раз ни к кому не принадлежит). Может быть гуру-программисты дадут более точное объяснение этому явлению...
Вчера мучался в догадках, почему под одной и той же ячейкой в
UITableView (одна ячейка в одной группе, стиль выбран
UITableViewStyleGrouped) появлялась одна и та же горизонтальная
полосочка. Баг был явно привязан именно к этой ячейке.
Оказалось, что я задавал высоту ячейки не как целое или округлённое до
целого число (то есть возвращал из метода heightForRowAtIndexPath
значение с заметной на экране дробной частью).
UITableView (одна ячейка в одной группе, стиль выбран
UITableViewStyleGrouped) появлялась одна и та же горизонтальная
полосочка. Баг был явно привязан именно к этой ячейке.
Оказалось, что я задавал высоту ячейки не как целое или округлённое до
целого число (то есть возвращал из метода heightForRowAtIndexPath
значение с заметной на экране дробной частью).
Случается так, что гигантские функции (в несколько тысяч строк кода) не позволяют собрать проект. Если нет ошибок компиляции, но есть непонятная ошибка линковки, то попробуйте в свойствах Xcode-проекта убрать галочку с пункта GCC 4.2 Code Generation - > Compile for Thumb. Мне это помогло (нашёл совет где-то в англоязычных сайтах).
Вот какие скрипты я использую для работы в 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}%%%\")
Новый 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 осталась без Стива Джобса, эта компания обречена потерять лидерские позиции? Я думаю, что очень даже может быть. Любое могущество основано на могуществе личности (это я прочитал у Наполеона Хилла).
Материал взят из http://connordenman.wordpress.com/2010/0 9/18/rotation-of-cgimage-iphoneipad-impr oved/
- (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;
}
Материал взят из http://iphonedevelopertips.com/data-file-m anagement/save-uiimage-object-as-a-png-o r-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]);
- (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
[^//][^ ]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).
Иногда бывает невозможно добавить существующий исходник в дерево проекта обычным способом (исходник или вообще какой-либо иной файл обозначен серым цветом, как будто бы он уже был добавлен в дерево проекта)
Тогда просто откройте вне проекта рядом папку с исходником (или иным нужным файлом) и перетащите нужный исходник (или файл) в дерево проекта в нужную группу
Удивительно, это работает!
Тогда просто откройте вне проекта рядом папку с исходником (или иным нужным файлом) и перетащите нужный исходник (или файл) в дерево проекта в нужную группу
Удивительно, это работает!