<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7667918330586312852</id><updated>2011-09-08T10:36:28.670-07:00</updated><category term='статическая библиотека.'/><category term='ar'/><category term='clang'/><category term='static analisator'/><category term='iPhone'/><category term='iPhone SDK'/><category term='IB plugins'/><category term='plugin'/><category term='Memory leaks'/><category term='Memory management Cocoa iPhone NSAutoreleasePool'/><category term='NSZombieEnabled'/><category term='статический анализ'/><category term='Leaks.'/><category term='Interface Builder'/><category term='Static library'/><title type='text'>Simple Cocoa</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7667918330586312852.post-1472497389951161245</id><published>2011-02-10T08:36:00.001-08:00</published><updated>2011-02-10T08:36:03.622-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Interface Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='IB plugins'/><title type='text'>Interface Builder plugins</title><content type='html'>&lt;p&gt;После продолжительного молчания хотелось бы написать для начала небольшую заметку, ну а там как пойдет...&lt;/p&gt;&lt;p&gt;Как источник вдохновления и поиска новых интересных решений для меня является просмотр и изучения OpenSource проектов. Иммено в них я впервые увидел плагины для IB. Достаточно полезная штука, как оказалось...&lt;/p&gt;&lt;p&gt;Плагин представляет собой файл с расширением &lt;strong&gt;*.ibplugin&lt;/strong&gt;. Для его установки в систему необходимо просто 2 раза кликнуть на него. Именно такой способ установки наткнул меня на мысль о том, что нормально компилируемый  проект на моем Maс'е совсем не значит что проект успешно соберется на другом... Собрав простенький проект и при попытке скомпилировать на другом, XCode выдал ошибку &lt;strong&gt;Unable to resolve plug-in dependency for "MainMenu.xib".&lt;/strong&gt; : Такое поведение нарушает один из принципов Continuous Integration. Гугл в этом вопросе мне не помог поэтому пришлось самому искать ответ. Первым делом я решил, что скорее всего пути можно прописать в самом XIB'e. Полазив по настройкам ничего подобного я не нашел. После этого я решил поискать соответствующие настройки в самом проекте.&lt;/p&gt;&lt;p&gt;Оказывается в настройках проекта XCoda можно найти целую секцию: &lt;strong&gt;Interface Builder XIB Compiler - Options&lt;/strong&gt; которая отвечает за настройки компиляции файлов IB. И в частности нас интересует пункт &lt;strong&gt;Plug-In Search Paths&lt;/strong&gt; Именно этот пункт отвечает за директорию в которой искать плагины. По этому для себя я определил структуру проекта: в корне проекта у меня находится папочка 3rdparty, в которой хранятся все сторонние библиотеки используемые в проекте. В папочке 3rdparty  находится подпапочка binaries, которая в частности отвечает за бинарные данные т.е. статические динамические библиотеки, плагины и т.д. Тогда путь к библиотекам и плагинам будет достаточно простой: &lt;strong&gt;$(SRCROOT)/3rd_party/binaries&lt;/strong&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7667918330586312852-1472497389951161245?l=simplecocoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/1472497389951161245/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://simplecocoa.blogspot.com/2011/02/interface-builder-plugins.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/1472497389951161245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/1472497389951161245'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/2011/02/interface-builder-plugins.html' title='Interface Builder plugins'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7667918330586312852.post-7370477586881726772</id><published>2009-10-06T07:28:00.000-07:00</published><updated>2009-10-07T00:01:31.010-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='static analisator'/><category scheme='http://www.blogger.com/atom/ns#' term='clang'/><category scheme='http://www.blogger.com/atom/ns#' term='статический анализ'/><title type='text'>Статический анализ кода</title><content type='html'>&lt;div style="text-align: justify;"&gt;&amp;nbsp;Недавно, в моем проекте возникла проблема. Суть ее заключалась в не стабильных крэшах приложения, которые было очень трудно воспроизвести и редко повторялись, но тем не менее они присутстовали, чем сильно раздражали. Главая из версий, объясняющая их была до банальности проста – не коректная работа с памятью. На поиски освобожденных / не освобожденных объектов было потрачено не один день. Было найдено и справленно несколько других багов связанных с памятью, но это не привело к ожидаемому результату.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&amp;nbsp;Буквально недавно, я узнал, что в Xcode 3.2 есть возможность статического анализа кода. Статический анализ – это анализ выполняемый над версией кода, с целью выявления мест содержащих ошибки. Встроеный в Xcode 3.2 анализатор, основан на консольном анализаторе clang. Если вы щасливый обладатель OS X Snow Leopard и Xcode 3.2, то советую вам прочитать статью из эпловской документации:&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="color: navy;"&gt;&lt;span lang="zxx"&gt;&lt;u&gt;&lt;a href="http://developer.apple.com/mac/library/featuredarticles/StaticAnalysis/index.html"&gt;http://developer.apple.com/mac/library/featuredarticles/StaticAnalysis/index.html&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;иначе читаем далее.&lt;br /&gt;&lt;br /&gt;Для начала нам предстоит установить анализтор clang. Для этого мы должны скачать архив &lt;span style="color: navy;"&gt;&lt;span lang="zxx"&gt;&lt;u&gt;&lt;a href="http://checker.minormatter.com/checker-0.223.tar.bz2"&gt;&lt;b&gt;checker-0.223.tar.bz2&lt;/b&gt;&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt; с сайта:&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="color: navy;"&gt;&lt;span lang="zxx"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: navy;"&gt;&lt;u&gt;&lt;a href="http://clang-analyzer.llvm.org/"&gt;http://clang-analyzer.llvm.org/&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="color: navy;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;и распаковать его, скажем, на рабочий стол. В итоге, на вашем рабочем столе, у вас окажется папка &lt;span style="color: black;"&gt;&lt;span style="font-family: LucidaGrande;"&gt;&lt;span style="font-size: small;"&gt;checker-0.223. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Теперь переместим папку  checker-0.223 в дирректорию /usr/bin. Запустите Терминал, перейдите на Рабочий стол и выполните команду:&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;b&gt;sudo mv checker-0.223 /usr/bin/&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;span style="font-weight: normal;"&gt;Теперь перейдите в папку &lt;/span&gt;&lt;b&gt;/usr/bin/ &lt;/b&gt;&lt;span style="font-weight: normal;"&gt;и создайте символьные ссылки на статический анализатор и просмотрщик результатов:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;b&gt;sudo ln -s checker-0.223/scan-build scan-build&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;b&gt;sudo ln -s checker-0.223/scan-view scan-view&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; На этом установка анализатора завершена. Перейдем непосредственно к настройке проэкта. Настраивать особо много не прийдется, только Code sign и Base SDK. Для настройки Code sign, зайдите в настройки таргета, на вкладку Build, перейдите в секцию Code signing и для ключа Any iPhone Device выберете Don't Code Sign:&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_oU_yRLX0hXM/Ssw6KZspxvI/AAAAAAAAAOE/zGVs4rcTJCM/s1600-h/Code+signing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/Ssw6KZspxvI/AAAAAAAAAOE/zGVs4rcTJCM/s320/Code+signing.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: center;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; Теперь зайдите в настройки проэкта, на вкладку General и выберите iPhone Simulator 2.1 для Base SDK for All Configurations.&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_oU_yRLX0hXM/Ssw6S-eIrBI/AAAAAAAAAOM/bVQTM1xtMNI/s1600-h/SDK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_oU_yRLX0hXM/Ssw6S-eIrBI/AAAAAAAAAOM/bVQTM1xtMNI/s320/SDK.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;На этом настройка проекта окончена, можно преступать непосредственно к билду и анализу, кода.&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;span style="font-weight: normal;"&gt; При установке Xcod'а, по умолчанию установливается замечательная консольная утилита &lt;/span&gt;&lt;b&gt;xcodebuild&lt;/b&gt;&lt;span style="font-weight: normal;"&gt;. Она позволяет собирать ваш проект из под консоли. Именно связка &lt;/span&gt;&lt;b&gt;xcodebuild&lt;/b&gt;&lt;span style="font-weight: normal;"&gt; + &lt;/span&gt;&lt;b&gt;scan-build&lt;/b&gt;&lt;span style="font-weight: normal;"&gt;, даст нам возможность найти баги в нашем коде.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;span style="font-weight: normal;"&gt; Создадим новый Window Based проект с названием TestProject и добавим в метод &lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;applicationDidFinishLaunching&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-weight: normal;"&gt; код:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;span style="color: #5c2699;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-weight: normal;"&gt;NSString&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-weight: normal;"&gt; *testString;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;/div&gt;&lt;div align="LEFT" class="western" style="margin-bottom: 0in;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #5c2699;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;NSString&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt; *testString2; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="LEFT" class="western" style="margin-bottom: 0in;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;    testString2 = [testString &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #2e0d6e;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;copy&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-family: Monaco,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="LEFT" class="western" style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="LEFT" class="western" style="margin-bottom: 0in;"&gt; &lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;&lt;i&gt;Сразу предупрежу вас, что код заведомо содержит ошибки. Они созданы с целью показать возможности статического анализатора.&lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: justify;"&gt;Теперь сохраним проект, запустим консоль и перейдем в папку проекта. Остается только выполнить статический анализ. Очень хорошо, перед каждым анализом очистить проект. Для этого вызовете команду:&lt;i&gt; &lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in; text-align: center;"&gt;&lt;span style="font-style: normal;"&gt;&lt;b&gt;scan-build xcodebuild  -configuration Debug clean&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; ну и после ее выполнения, запустите сам статический анализатор:&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: center;"&gt;&lt;b&gt;scan-build -k -V xcodebuild -configuration Debug&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; В результате, после билда и анализа у вас в консоль напишется что то типа того:&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_oU_yRLX0hXM/Ssw7L_Ixo4I/AAAAAAAAAOU/PGxxzQ7eiuE/s1600-h/Console+output.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/Ssw7L_Ixo4I/AAAAAAAAAOU/PGxxzQ7eiuE/s320/Console+output.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; И по идеи, должен запуститься браузер с отчетом о найденых багах. Но к сожалению не всегда это происходит. Если у вас такой случай, то не беспокойтесь, просто перейдите по пути, вывевшемся в консоли и запустите вручную файл отчета:&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="CENTER" class="western" style="font-style: normal; margin-bottom: 0in;"&gt; &lt;b&gt;cd /var/folders/qE/qEWzPoglGVWOVJJ2d-amzU+++TI/-Tmp-/scan-build-2009-10-05-1&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="CENTER" class="western" style="font-style: normal; margin-bottom: 0in;"&gt; &lt;b&gt;open index.html&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="CENTER" class="western" style="font-style: normal; margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; margin-bottom: 0in; text-align: justify;"&gt;В результате у вас загрузится браузер, в котором будет html отчет отображающий результат анализа:&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_oU_yRLX0hXM/Ssw7gXn-P0I/AAAAAAAAAOc/lqFwj0KRU3g/s1600-h/html+report.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_oU_yRLX0hXM/Ssw7gXn-P0I/AAAAAAAAAOc/lqFwj0KRU3g/s320/html+report.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;Сам отчет разделен на 3 части:&lt;br /&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;информация о билде (пользователь, дата  путь);&lt;/li&gt;&lt;li&gt;количество найденных багов, разбитые  на категории;&lt;/li&gt;&lt;li&gt;список файлов, в которых найдены баги.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: justify;"&gt;  Для удобства вы можете выбрать определенный тип ошибок, убрав или проставив галочки. Наибольший же интерес для нас представляет раздел Reports, в котором, как сказанно выше, отображается список файлов в которых найдены баги. Нажав на ссылку View Report, вы можете просмотреть подробный отчет по определенной ошибке в файле. В подробном отчете отображается линия в которой найдено уязвимое место и примерное описание что не так. Вам остается хорошенько проанализировать код, ведь анализатор не искуственный интеллект, и если уязвимость подтверждается, исправить ее.&lt;/div&gt;&lt;div style="text-align: justify;"&gt; &lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Если честно, для меня остается загадкой, по какому приницпу определяются файлы в которых присутствуют ошибки. Так как бывали такие места, в которых явно были “опсные” места, а анализатор не помечал их. Надеюсь в ближайшем будущем я разберусь в этом и подправлю статью. Хоть анализатор нашел в проекте несколько критических утечек, но все равно приходится быть внимательным. Чего и вам желаю. &lt;/div&gt;&lt;div class="western" style="font-style: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal; font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-weight: normal; margin-bottom: 0in; text-align: justify;"&gt; &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7667918330586312852-7370477586881726772?l=simplecocoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/7370477586881726772/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://simplecocoa.blogspot.com/2009/10/blog-post_06.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/7370477586881726772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/7370477586881726772'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/2009/10/blog-post_06.html' title='Статический анализ кода'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_oU_yRLX0hXM/Ssw6KZspxvI/AAAAAAAAAOE/zGVs4rcTJCM/s72-c/Code+signing.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7667918330586312852.post-5142959775789777517</id><published>2009-10-01T07:45:00.000-07:00</published><updated>2009-10-04T11:23:50.205-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NSZombieEnabled'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaks.'/><category scheme='http://www.blogger.com/atom/ns#' term='Memory leaks'/><title type='text'>Борьба с утечками памяти</title><content type='html'>Наверное 90% крэшей приложения связанно с некоректной работой с памятью. Иногда, в большом проэкте, чтоб отловить такой крэш может затратиться значительное время. И хорошо, когда по внешним признакам падения приложения(то есть на каком экране или при каких действия пользователя) можно определить из за чего именно оно упало. Но к сожалению не всегда так. Какие же первые меры необходимо принять, после крэша? На мой взгляд самое логичное и простое – это посмотреть, что вывелось в консоль дебагера. Чаще всего в консоли можно увидеть такое сообщение:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/SsTA0BGczNI/AAAAAAAAAM0/z5yMrGLa818/s1600-h/Unrecognized+selector.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 205px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/SsTA0BGczNI/AAAAAAAAAM0/z5yMrGLa818/s320/Unrecognized+selector.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387643054123175122" /&gt;&lt;/a&gt;&lt;br /&gt;Первая фраза, из сообщения:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-[NewObject show]: unrecognized selector sent to instance 0x12179b0&lt;/span&gt;&lt;br /&gt;указывает на то, что у объекта NewObject был вызван не существующий метод show. Здесь, все просто – возможны 2 варианта:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;вы просто ошиблись с именем метода или со списком передваемых параметров;&lt;br /&gt;&lt;li&gt;NewObject не NewObject, а что то другое. Такой вариант возможен, когда вы используете авторелизные объекты. Вы посылаете сообщение объекту, который был уже освобожден и в итоге в переменной хранятся некоректные данные (к примеру указатель на другой объект). Так что вам предстоит кропотливый поиск освобожденного объекта.&lt;br /&gt;&lt;/ul&gt;Но за частую консоль не предоставляет никакой отладочной информации. Для такого случая в Xcode предоставляется средство позволяющее ускорить процесс поиска освобожденного объекта. Для активации этого средства необходимо прописать переменную окружения NSZombieEnabled и установить ее значение в YES. Для этого в группе Executables вызовте свойства для вашего executable:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTBfsPsqFI/AAAAAAAAAM8/kZP9JObPYTk/s1600-h/Executables.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 182px; height: 37px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTBfsPsqFI/AAAAAAAAAM8/kZP9JObPYTk/s320/Executables.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387643804439062610" /&gt;&lt;/a&gt;В появившемся окне перейдите на вкладку Arguments добавте перменную окружения NSZombieEnabled и установите ее значение YES. В итоге у вас должно быть нечто вроде этого:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_oU_yRLX0hXM/SsTBnVfWyeI/AAAAAAAAANE/zGoedi090C8/s1600-h/Executables+-+Arguments.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 211px; height: 320px;" src="http://2.bp.blogspot.com/_oU_yRLX0hXM/SsTBnVfWyeI/AAAAAAAAANE/zGoedi090C8/s320/Executables+-+Arguments.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387643935769676258" /&gt;&lt;/a&gt;Теперь можете опять попробовать запустить приложение. В этом случае сообщение будет посодержательней:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTB3cd5I2I/AAAAAAAAANM/gMt7YYE93y4/s1600-h/NSZombieEnabled.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 20px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTB3cd5I2I/AAAAAAAAANM/gMt7YYE93y4/s320/NSZombieEnabled.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387644212520493922" /&gt;&lt;/a&gt;Ну а далее – знание проекта и ваша интуиция...Эти способы хорошо применять на часто повторяющихся крэшах, которые удается воспроизвести при определенных действиях. Но  иногда возникает такое ощущние, что программа начала жить своей жизнью. То работает, работает при определенных действиях, а потом ни с того ни с его падает. В такой ситуации следует вводить “тяжелую артилерию”.  Под тяжелой артилерией я понимаю интсрумент Leaks и статический анализатор кода, о котором я расскажу в следующей статье.Leaks – утилита, которая в реалтайме анализирует выделяемую и освобождаемую память и на основе полученных данных отображает объекты, которые утекают. Для того, чтоб запустить Leaks, выберете в меню Run – Start with Performance Tools – Leaks. Приложение установится в телефон/симулятор и запустится на выполнение. При этом у вас появится окно инструмента Leaks:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/SsTCSdKfAuI/AAAAAAAAANU/1Xh1CbrZEtg/s1600-h/Leaks.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 204px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/SsTCSdKfAuI/AAAAAAAAANU/1Xh1CbrZEtg/s320/Leaks.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387644676563993314" /&gt;&lt;/a&gt;Верхняя часть, ObjectAlloc, говорит нам о размере потребляемой памяти приложением.  Нижняя часть – утечки памяти в прогамме. Если Leaks обнаруживает лики, они сразу же отобажаются в виде оранжевых пик и в виде записи процент – размер – адрес – объект. Более детальную ифнормацию вы можете посмотртеть в строке адреса, нажав на кружочек со стрелочкой:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTCzLiizGI/AAAAAAAAANc/9YNnhMLNTNo/s1600-h/circle.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 107px; height: 51px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/SsTCzLiizGI/AAAAAAAAANc/9YNnhMLNTNo/s320/circle.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387645238768749666" /&gt;&lt;/a&gt;В появившемся окне наибольший инетерес вызывает столбец Responsible Caller, в который заносится метод и имя класса, у которого был вызван метод, произвевший утечку памяти. Остается только найти этот метод и исправить утекаемый объект.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7667918330586312852-5142959775789777517?l=simplecocoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/5142959775789777517/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://simplecocoa.blogspot.com/2009/10/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/5142959775789777517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/5142959775789777517'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/2009/10/blog-post.html' title='Борьба с утечками памяти'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_oU_yRLX0hXM/SsTA0BGczNI/AAAAAAAAAM0/z5yMrGLa818/s72-c/Unrecognized+selector.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7667918330586312852.post-6084289240829212690</id><published>2009-09-21T03:51:00.000-07:00</published><updated>2009-09-21T05:39:10.045-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Memory management Cocoa iPhone NSAutoreleasePool'/><title type='text'>Memory management</title><content type='html'>&lt;span style="font-style:italic;"&gt;Одной из главных проблем, с которой сталкивается начинающий разработчик под iPhone, является не понимание принципов управления памятью в Cocoa, которым и посвящается данная статья.&lt;/span&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Итак, начнем с самого начала. Как нам известно, в Objective C все строится вокруг динамических объектов. Это ведет к  более рациональному использованию памяти, так как мы управляем, когда освободить объект и занимаемую им память. Из этого следует, что у каждого объекта должен быть свой владелец, от этого будет зависеть, кто должен освободить объект. Каким образом можно определить, кто является владельцем объекта? В Cocoa есть простое правило – владельцем объекта является тот, кто создал его. То есть, если вы не посылали объекту сообщение содержащее alloc, copy или new, то можете не переживать, вы не владелец объекта и вам не надо заботиться об освобождении его. Иначе прийдется считать ссылки, увеличивать, уменьшать их количество… Рассмотрим пример:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_oU_yRLX0hXM/Srdv0MKQHCI/AAAAAAAAAL8/MaJfgXl33LQ/s1600-h/Wrong+example.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 61px;" src="http://2.bp.blogspot.com/_oU_yRLX0hXM/Srdv0MKQHCI/AAAAAAAAAL8/MaJfgXl33LQ/s320/Wrong+example.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383894821952822306" /&gt;&lt;/a&gt;&lt;br /&gt;Это не правильно поведение, так как функция print не являетесь владельцем объекта strPrintText. Исправим пример:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdwftKzs3I/AAAAAAAAAME/7PPCjxzBbDE/s1600-h/Correct+example.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 37px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdwftKzs3I/AAAAAAAAAME/7PPCjxzBbDE/s320/Correct+example.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383895569547899762" /&gt;&lt;/a&gt;&lt;br /&gt;Что же значит увеличивать уменьшать количество ссылок? В Objective C управление памятью основывается на подсчете ссылок. Все классы в иерархии наследования имеют общего предка — класс NSObject. NSObject содержит в себе счетчик ссылок (retaintCount). И методы позволяющие управлять счетчиком. При создании объекта, переменной retainCount будет присвоено значение 1 и объект будет существовать до тех пор, пока retainCount не станет равен нулю. Как только это случится, объекту будет послано сообщение dealloc и объект удалится. Для увеличения/уменьшения количества ссылок в NSObject'e есть 3 метода reatin, release и autorelease. И еще 2, которые не посредственно влияют на счетчик: alloc и copy. Для того, чтоб увеличить счетчик ссылок на 1 объекту необходимо послать сообщение retain, для уменьшения – release. Есть еще метод autorelese, который уменьшает количество ссылок на 1, но через время.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Из вышесказанного можно выделить несколько простых правил по управлению памятью:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;только владелец объекта должен освобождать объект;&lt;br /&gt;&lt;li&gt;сообщение release должно посылается объекту столько раз, сколько раз были посланы ему сообщения retain, alloc, new или copy.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;На мой взгляд, наибольшей неразберихи в этом простом процессе вводят авторелизные объекты. И по сему хотелось остановиться на них поподробнее.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Как говорилось выше авторелизный объект — это объект, которому было послано сообщение autorelease и у которого количество ссылок уменьшится на 1 спустя какое то время. Для осуществления этого механизма в Cocoa предусмотрен менеджер авторелизных объектов  - NSAutoreleasePool. Образно говоря пул представляет из себя стэк, хранящий в себе ссылки на авторелизные объекты. После посылки объекту сообщения autorelease, ссылка на объект копируется в ближайший пул и находится там до тех пор, пока пул не будет освобожден или ему не будет послано сообщение drain. В этом случае всем объектам находящимся в пуле будет послано сообщение release, причем столько раз, сколько им было послано сообщение autorelease. Так что будьте аккуратней. Вся хитрость использования авторелизных объектов заключается в том, что вы наверняка не знаете когда они освободятся. В Cocoa приложении существует как минимум 1 пул. В этом вы можете убедиться взглянув в файл main.m вашего проекта. Но кроме этого Application Kit автоматически  создает свой пул  на каждый новый поток или, к примеру,  обработчик события, так что в какой именно пул попадет объект и когда он освободится вы точно не знаете(Хочу заметить, что если поток создаете вы, то вы обязаны сами создать пул).&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Очень часто бывает, что написав код, протестировав его, он работает прекрасно, а потом неожиданно, без видимой причины приложение валится. На 90% - это пул пытается освободить уже освобожденный обект. Так что можете смело начинать считать ссылки. Кроме того, чрезмерное использование авторелизных объектов ведет к переполнению памяти мусором, а позже и к крэшу приложения. Прочитав выше написанное получается, что авторелизный пул лучше не использовать ну или по крайней мере свести его применение к минимуму. Лично я поддерживаю это мнение, но как показывает практика, без него никуда не деться.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Когда же использовать авторелизные объекты? Давайте рассмотрим заведомо не правильный пример:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdxykiHOWI/AAAAAAAAAMM/xdaWdo62Zs4/s1600-h/Wrong+example+2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 123px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdxykiHOWI/AAAAAAAAAMM/xdaWdo62Zs4/s320/Wrong+example+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383896993158871394" /&gt;&lt;/a&gt;&lt;br /&gt;Так делать не правильно, так как функция print не является владельцем объекта  string. Память под объект  string была выделена в фунцкии getString, значит там и должна быть освобождена. Исправим пример:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdypvHjf6I/AAAAAAAAAMU/bGqg45pZ8Gs/s1600-h/Correct+example+2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 116px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/SrdypvHjf6I/AAAAAAAAAMU/bGqg45pZ8Gs/s320/Correct+example+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383897940893073314" /&gt;&lt;/a&gt;&lt;br /&gt;То есть, можно сформировать следующее правило:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;используйте авторелизные объекты только тогда, когда вам их необходимо передать в качестве возвращаемого значения функции.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;А далее или увеличивайте количество ссылок или копируйте объект.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Не выполнение этих 3х простых правил, как правило, ведет к утечкам памяти или частым крэшам приложения. В следующей статье я опишу методы борьбы с утечками и крэшами связанными с не корректной работой с памятью.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7667918330586312852-6084289240829212690?l=simplecocoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/6084289240829212690/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://simplecocoa.blogspot.com/2009/09/memory-management.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/6084289240829212690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/6084289240829212690'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/2009/09/memory-management.html' title='Memory management'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_oU_yRLX0hXM/Srdv0MKQHCI/AAAAAAAAAL8/MaJfgXl33LQ/s72-c/Wrong+example.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7667918330586312852.post-3426369887797735658</id><published>2009-09-03T07:37:00.000-07:00</published><updated>2010-11-22T00:50:58.535-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Static library'/><category scheme='http://www.blogger.com/atom/ns#' term='static analisator'/><category scheme='http://www.blogger.com/atom/ns#' term='NSZombieEnabled'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaks.'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone SDK'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='статическая библиотека.'/><category scheme='http://www.blogger.com/atom/ns#' term='clang'/><category scheme='http://www.blogger.com/atom/ns#' term='Memory management Cocoa iPhone NSAutoreleasePool'/><category scheme='http://www.blogger.com/atom/ns#' term='статический анализ'/><category scheme='http://www.blogger.com/atom/ns#' term='Memory leaks'/><category scheme='http://www.blogger.com/atom/ns#' term='ar'/><title type='text'>iPhone static library</title><content type='html'>Библиотеки были придуманы для объединения схожей функциональности в отдельные модули, которые могли использоваться совместно несколькими разработчиками.&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;p style="margin-bottom: 0in; text-align: justify;"&gt;В мире *nix систем да и вообще в мире OC  существует 2 вида библиотек. &lt;/p&gt;&lt;ol&gt;&lt;li&gt;динамические;&lt;/li&gt;&lt;li&gt;статические.&lt;/li&gt;&lt;/ol&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;Каждый тип библиотек имеет свои достоинства и не достатки. Прозрачный механизм создания динамических библиотек под iPhone отсутствует, хотя лично мое мнение – я не вижу большого смысла в использовании их под  iPhon'ом. Нам же, наибольший интерес, представляют статические библиотеки, речь о которых пойдет далее в статье.&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;Статическая библиотека – это хороший способ повтороного использования кода. Кроме того, в некоторых проектах, при использовании множества не маленьких OpenSource – решений применение статических библиотек – отличный вариант сократить время на перекомпиляцию проекта. Это достигается путем хранения заранее обработанного компилятором исходного кода в объектные файлы.&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt; В nix системах, как правило, статические библиотеки имеют расширение *.a. Таким образом, статическая библиотека – это архив, содержащий в себе объектные файлы.&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;То что это архив, а не, скажем, цельный бинарник, вы можете убедиться путем разархивации его. Для этого вам необходимо в терминале выполнить комнаду:&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="CENTER"&gt;&lt;span style="font-weight: bold;"&gt;ar -x&lt;/span&gt;&lt;i&gt;имя_статической_библиотеки&lt;/i&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in; text-align: justify;"&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in; font-style: normal; font-weight: normal;" align="JUSTIFY"&gt; В результатет, в том же каталоге, у вас должны появиться распакованные объектные файлы.&lt;/p&gt;&lt;p style="margin-bottom: 0in; font-style: normal; font-weight: normal;" align="JUSTIFY"&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in; font-style: normal; font-weight: normal;" align="JUSTIFY"&gt; Итак, перейдем к практике. Практиковаться мы будем, на свежесозданном проекте и исходниках обертки над sqlite – FMDatabase.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ol style="text-align: justify;"&gt;&lt;li&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;    Для этого создадим новый проект, к  примеру Window-based Application, (тип проекта  может быть любой) и назовем его  MakeStaticLib. Далее, для удобства, создадим  новую группу для обертки, привяжем ее  к папке и добавим в нее исходники.&lt;/li&gt;&lt;li&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;    Нажмем правой кнопкой, на группу Classes  и выберем пункт &lt;span style="font-weight: bold;"&gt;Add&lt;/span&gt; – &lt;span style="font-weight: bold;"&gt;New group&lt;/span&gt;. Свежесозданную  группу назовем FMDatabase и создадим для  нее одноименную папку. Для этого зайдем  в свойства группы FMDatabase, нажмем на  кнопку Choose и выберем папку, где мы хотим  хранить исходники.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_WlS7uIrI/AAAAAAAAALM/GHRNSBeDpPg/s1600-h/Make+folder+for+group.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 114px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_WlS7uIrI/AAAAAAAAALM/GHRNSBeDpPg/s320/Make+folder+for+group.png" alt="" id="BLOGGER_PHOTO_ID_5377252416329491122" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Добавим исходники FMDatabase в проект, (взять их можно с сайта &lt;span style="color: rgb(0, 0, 128);"&gt;&lt;span lang="zxx"&gt;&lt;u&gt;&lt;a href="http://code.google.com/p/flycode/"&gt;http://code.google.com/p/flycode/&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/li&gt;&lt;li&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;  На этом  подготовительная часть окончена, теперь  приступим непосредственно к созданию  библиотеки. Для этого нажмем правой  кнопокй на раздел &lt;span style="font-weight: bold;"&gt;Targets&lt;/span&gt; и выберем пункт &lt;span style="font-weight: bold;"&gt; Add&lt;/span&gt; – &lt;span style="font-weight: bold;"&gt;New Target&lt;/span&gt;.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_oU_yRLX0hXM/Sp_pQgkzhPI/AAAAAAAAAL0/JxndZ8wvTrI/s1600-h/Add+new+target+2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 227px;" src="http://3.bp.blogspot.com/_oU_yRLX0hXM/Sp_pQgkzhPI/AAAAAAAAAL0/JxndZ8wvTrI/s320/Add+new+target+2.png" alt="" id="BLOGGER_PHOTO_ID_5377272949935146226" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;  В появившемся  окне выберем тип target'а  Static Library, назовем  ее FMDatabase и нажмем Finish. В результате  структура проекта должна получиться  следующая:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_aznjhnxI/AAAAAAAAALU/xtaouMvR3_E/s1600-h/Project+structure.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 135px; height: 320px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_aznjhnxI/AAAAAAAAALU/xtaouMvR3_E/s320/Project+structure.png" alt="" id="BLOGGER_PHOTO_ID_5377257060429831954" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Теперь  приступим непосредственно к добавлению  исходников к статической библиотеки.  Здесь прячется небольшая хитрость.  Дело в том, что при добавлении исходников  в проект, по умолчанию они добавляются  в главный таргет, а он у нас является  MakeStaticLib. На простороах сети, в основном,  я встречал способ, при котром  файлы  добавлялись напрямую в Static lib target, но к  сожалению с первого раза я не  смог  повторить этот трюк и нашел другой, на  мой взгляд, более красивый способ.  Для     этого выберем ТОЛЬКО *.m файлы, которые  мы хотим, чтоб присутствовали в   библиотеке, выбрем у них пункт Get Info,  перейдем на вкладку Targets и сменим  “пункт  назначения” c MakeStaticLib на FMDatabase:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_bkdOqd7I/AAAAAAAAALc/lcca3pLb-uM/s1600-h/Change+target.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 118px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_bkdOqd7I/AAAAAAAAALc/lcca3pLb-uM/s320/Change+target.png" alt="" id="BLOGGER_PHOTO_ID_5377257899471566770" border="0" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;  Далее добавим   библиотеку в наш проект. Для этого мы   зайдем в свойства таргета MakeStaticLib на   вкладку &lt;span style="font-weight: bold;"&gt;General&lt;/span&gt;, и выберем один из 2х   способов. Первый способ заключается   в том, что мы добавим библиотеку как   &lt;span style="font-weight: bold;"&gt;Direct dependencies&lt;/span&gt; объект. Это дает возможность,   после изменения кода библиотеки,   автоматически перекомпилировать   статическую библиотеку во перекомпиляции   всего проекта.  Иначе, если вы вебрете   второй способ, добавления библиотеки   как &lt;span style="font-weight: bold;"&gt;Linked Libriries&lt;/span&gt; объект, вам будет необходим   сперва перекомпилировать библиотеку   вручную, а потом сам проект. На мой   взгял это не совсем удобно и я бы вам   порекомендовал добавлять как  &lt;span style="font-weight: bold;"&gt;Direct   dependencies&lt;/span&gt; объект.&lt;/li&gt;&lt;li&gt;&lt;style type="text/css"&gt;&lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;  И наконец   последний пункт, который многие не   понимают зачем делать, так как и без   него все работает. Для того, чтобы в   библиотеки нормально отрабатывали   возможности языка Objective C (к примеру   категории) необходимо добаить флаг   &lt;span style="font-weight: bold;"&gt;-ObjC&lt;/span&gt; к флгам линковщика (Other linker flags).   Делается это в Info таргета MakeStaticLib, на   вкладке &lt;span style="font-weight: bold;"&gt;Build&lt;/span&gt; в секции &lt;span style="font-weight: bold;"&gt;Linking&lt;/span&gt;.   &lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_cEvNRHYI/AAAAAAAAALk/cdn4ncyh148/s1600-h/Other+linker+flags.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width:&lt;br /&gt; 320px; height: 136px;" src="http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_cEvNRHYI/AAAAAAAAALk/cdn4ncyh148/s320/Other+linker+flags.png" alt="" id="BLOGGER_PHOTO_ID_5377258454053363074" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;На этом создание статической библиотеки окончено.&lt;br /&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;" align="JUSTIFY"&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in; text-align: justify;"&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in; font-style: normal; font-weight: normal;" align="JUSTIFY"&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7667918330586312852-3426369887797735658?l=simplecocoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simplecocoa.blogspot.com/feeds/3426369887797735658/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://simplecocoa.blogspot.com/2009/09/iphone.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/3426369887797735658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7667918330586312852/posts/default/3426369887797735658'/><link rel='alternate' type='text/html' href='http://simplecocoa.blogspot.com/2009/09/iphone.html' title='iPhone static library'/><author><name>Тухтаров Владислав</name><uri>http://www.blogger.com/profile/01267851186222303502</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_oU_yRLX0hXM/Sp_WlS7uIrI/AAAAAAAAALM/GHRNSBeDpPg/s72-c/Make+folder+for+group.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
