28 Ağustos 2012 Salı

How to properly use UIViewController and UIView on ios

I believe it's one of the biggest common misconceptions in writing for ios platform that every view should have a corresponding controller, specifically UIViewController.

I myself did this mistake when I first started writing ios applications too. I wasn't very experienced in writing UI code, so I didn't know MVC in detail. That might be the case for most of the people who makes this mistake. And since ios platform does not enforce you to avoid it, you are free to do it. (See how Android activities encourage you to use one Activity for a page which covers the entire screen)

Essentially, in MVC pattern, controller is the object which makes the communication between views in one page of the screen. Controller is not the delegate of a single view. Think of it in that way, if you need a static delegate object for a view class, why not do that delegating in that view itself?

Obviously, the view elements in UIKit which covers only a portion of the screen, such as UILabel, UIButton, UITableView are all subclasses of UIView. You don't need a seperate view controller for each instance of them. Even for UITableView you can assign an object as datasource and delegate and use it without a controller. Happily, we can say at least creators of the platform follow MVC correctly.

Prior to ios5, Apple did not even supported using multiple controllers by not calling view lifecycle methods(viewwilldisappear, viewdidload, etc) on controllers in deep hierarchy. But I believe since loading of a UIView from a nib was not explicitly and easily seen compared to loading a UIViewController, people preferred using a UIViewController per view element and that led to this biggest misconception.

From the day I got this enlightment that multiple view controllers in a page is unnecessary, I am trying to use UIView objects directly. I use KVO in views to listen model when possible. If the views are generic containers like UITableView, I create NSObject instances for them to act as delegate and/or datasource. I believe this is a more proper and tidy way of managing UI objects in code.

If you have different solutions or improvements to this approach, feel free to share your comments on the subject!

Some sources which discuss the same thing:
http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/
http://stackoverflow.com/a/5691708/369001

27 Ağustos 2012 Pazartesi

Mevcut kodu svn'den git'e taşımak

Neden öyle oluyor bilmiyorum, ama herhalde çoğumuz ilk reposunu svn'de oluşturmuş, ilk commit'ini falan svn'le yapmıştır. Bunda herhalde svn'in baştaki öğrenme sürecinin düşük olmasının etkisi vardır. Nitekim svn'den git'e ilk geçişte de git biraz karışık gelebiliyor. Ama git'i bir kere öğrenip- ki karmaşık dediysem zorluktan değil yarım saatlik araştırmaya üşenmekten- geriye dönüp svn'e bakınca insan svn'de geçirdiği zamanına acıyor. O yüzden svn kullananlara önerimdir, bir an önce git'e geçiniz. Hele ki bu iş bir komut kadar kolaysa

İşimizi halleden komut şu:
git svn clone http://svn/repo/here/trunk
Bu komutla git svn reposundan bütün revizyonları tek tek çekiyor ve lokalde bunları git yapısına uygun olarak birleştiriyoruz. git log dediğiniz zaman da commit'i yapanın kullanıcı adını nasıl oluşturduğunu bilmediğim bir mail adresi ile birlikte düzgün gösteriyor. Kimin neye katkıda bulunmuş olduğu bilgisi kaybolmuyor yani.

E-mail adreslerini düzeltme:
Commit log'larındaki email adreslerini düzgün görmenin iki yolu var.

İlkinde(önerdiğim yöntem) en baştan bir txt dosyası vererek her kullanıcının ad soyad ve emailini girebilirsiniz. txt dosyasının formatı şu şekilde:
user1 = First Last Name 
user2 = First Last Name 
...
Bu dosyayı ilk komutumuza
-A dosya.txt
ek ayarı ile veriyoruz.

İkincisinde ise taşınmayı gerçekleştirdikten sonra aşağıdaki script ile belirli bir email adresindeki bütün commitleri değiştirebilirsiniz:
    git filter-branch --env-filter '
      if [ "$GIT_AUTHOR_EMAIL" = "wrong email" ];
      then
          export GIT_AUTHOR_EMAIL="correct email";
      fi
      ' HEAD

Bu komutla svn reposunu git'e kolaylıkla taşımış olduk. Verdiğim komutla branch'lerin ve tag'lerin taşınmamış olduğuna dikkat ediniz. Eğer standart bir klasör yapınız varsa (tags, branches, trunk) --stdlayout opsiyonu ile branch ve tag'ları birer remote branch olarak çekebilirsiniz. Bu durumda en son komutumuz aşağıdaki gibi olacaktır:
git svn clone --stdlayout -A dosya.txt http://svn/repo/here/trunk
Branch'leri remote branch olarak aldıktan sonra karşılık gelen local branch'leri oluşturmamız gerekecek. Tag'ler de branch olarak geldiğinden branch'lerin içine girip tag olarak eklememiz gerekecek. Yapmak isteyenler için git'i ilk defa kullanacaklarsa güzel bir alıştırma :)

Yeni git reponuz hayırlı olsun. Artık gelsin local branch'ler, stash'ler, cherry-pick'ler, rebase'ler...


8 Ağustos 2012 Çarşamba

BUDatePicker - A versatile datepicker

I think it was a little P.I.A. to use default UIDatePicker provided by Apple. Then I thought writing an alternative date picker.

 Those are the things about UIDatePicker that does not satisfy me:

  • If user has not selected a date completely(i.e. spinner is still spinning) it does not give the closest date to spinner. It simply returns the date before spinning started.
  • You can not control wrapping of months and days 
  • You can not control showing areas out of boundaries or not 
  • You can not easily control places of month, day and year components. 


 BUDatePicker aims to solve those problems. It is not a complete solution though, because I have not alloted much time on it. Nevertheless, I think it is way more versatile and easy to use than standard UIDatePicker. And best of all it is open source.

 You can check it out at https://github.com/ucarbehlul/BUDatePicker

 Feel free to contribute or fork!