First roadmap

Most of time all blog posts written with my native tongue. From now on, I decide to write all blog posts  in english. So this helps me improve my english skills. I know it will be hard in beginning but have to. Every time I deem to how improve my english may be this way should be great. This is my first roadmap. In coming days I can add other things about my road.

Advertisements

iOS Check if string empty?

Evet kısa bir code-snippet paylaşacağım. Daha sonra bunun üzerine bir kaç bir şey daha ekleyeceğim. Şimdi yeni öğrendiğim ve bu konu üzerine geçmiş soru işaretlerim olduğu için daha detaylı bir arama ile blog yazısı paylaşacağım. Ama aşağıdaki kod basit olarak bir NSString değerinin boş olup olmadığını kontrol ediyor. Bunun için bir macro yapılabilir.

#define allTrim( object ) [object stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet] ]

Daha sonra kodda bunu kontrol edebilmek için;

NSString *emptyString = @"   ";

if ( [allTrim( emptyString ) length] == 0 ) NSLog(@"Is empty!");

Kod iki şekilde de çalışabilir isterseniz @”” şekilde de deneyebilirsiniz.

Ayrıca aşağıdaki kaynakları da kontrol edebilirsiniz.

http://blog.wilshipley.com/2005/10/pimp-my-code-interlude-free-code.html

http://stackoverflow.com/questions/899209/how-do-i-test-if-a-string-is-empty-in-objective-c

Behaviour Driven Development (for iOS) ?!

Evet. Başlıkta da vurgulandığı(?!) gibi nedir bu BDD? Neden kullanmalıyız? Gibi soruları elimden geldiğince uzun bir blog yazısı olarak paylaşmaya çalışacağım. İlk olarak söylemek gerekir ki Better Software‘in yayımladığı daha sonradan bir çok dile çevirildiği içinde Selim Ober’in Türkçe diline çevirdiği BDD giriş yazısını okumanızı tavsiye ederim. Ayrıca TDD ve BDD arasındaki farklıları açıklayan bir blog yazısı da burada.

Frameworks

Cedar
https://github.com/pivotal/cedar

Kiwi
https://github.com/kiwi-bdd/Kiwi

Specta
https://github.com/specta/specta

Specta guide for writing specs

iOS Block-code with Property

Yeni yıla girdik malum. Benim normalde de tüm yılım bilgisayar başında geçtiği için yeni yıla da bilgisayarım ile kod yazarak girdim 🙂 Pişman mıyım. Tabii amsterdam’da yılbaşı kutlamak ya da başka bir yerde çılgınca eğlenip yılbaşı kutlamak daha cazip geliyor. Ancak kendi koyduğum hedefler doğrultusunda çok çalışmam gerek. Şimdiden kendime 2015 yılı öğrenme takvimi gibi bir şey hazırladım 🙂

Neyse konuya gelelim. Block-code Objectvice-C’de en çok kullandığım özelliklerden birisi. Çok severim. Hem kullanırlığı kolay hem OO(Object Oriented) yapısına oldukça musait. Şimdi;

Interface dosyamızın hemen üstüne bir type-definition yani typedef oluşturuyoruz;

typedef void(^DoSomething)(void);

Daha sonra interface dosyamızda property olarak tanımlayabiliriz.

@property (nonatomic, copy) DoSomething somethingBlock;

Implementasyon dosyamızda “.m” istediğimiz işlemleri gerçekleştirebiliyoruz. Ben sadece NSLog ile bir şeyler yazdırdım. Tabii objemizin instantie edilmiş olması gerekiyor.


SomeClass *class = [[self alloc] init];

class.somethingBlock = ^{
        NSLog(@"Hello new year!!");
    };

Şimdi kullanmak istediğimiz sınıfımdızda dot syntax yaparak kullanbiliriz.


SomeClass *class = [[SomeClass alloc] init];
class.somethingBlock();

iOS TextView Prefix

Yaptığımız projelerin bazı noktalarında text girdilerine ön ek “prefix” koymak isteyebiliriz. Bu telefon kodu olabilir, “Sayın” gibi ifadeler de kullanabiliriz. Kullandığımız bu ön eklerin silinmemesi için “UITextField” sınıfının “UITextViewDelegate” delege methodlarından olan “textView:shouldChangeTextInRange:replacementText” methodunu kullanarak yapabiliriz.

Yapmamız gereken ilk olarak önceki metin ile sonraki metinleri birleştirmek. Daha sonra bu birleşimi bir NSString değişkeni içerisinde tutup daha sonra if-else koşulu ile eklediğimiz ön ek metin değerin uzunluğunu kontrol edip eğer birleştirilen metin belirtiğimiz ön ek metinin uzunluğundan küçük ise ön ekimizin silinmesini engelliyoruz. Bunu aşağıdaki kod ile yapabilirsiniz;

Prefix “Ön Ek” değerimiz

static NSString *const PREFIX_TEXT = @"Merhaba, ";

TextView’ımıza ekleceğimiz ön eki giriyoruz.

myTextView.text = PREFIX_TEXT;

Daha sonra delege metodumuzla kontrolleri sağlıyoruz.



- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    // Eski text değeriyle yenisini birleştiriyoruz...
    NSString *combinedText = [textView.text stringByReplacingCharactersInRange:range withString:text];
    
    // Eğer kullanıcı 4. karakterlerden sonraki karakterleri silmek istiyorsa bir prefix oluşturuyoruz
    // daha sonra text'in başına ön ek koyuyoruz.
    if(combinedText.length < 4) {
        textView.text = PREFIX_TEXT;
        return NO;
    }
    else if(![[textView.text substringToIndex:4] isEqualToString:[combinedText substringToIndex:4]]) {
        return NO;
    }
    
    return YES;
    
}

iOS Table Empty View

Listeleme gerektiren ya da ekleme – çıkarma yaptığımız Table View bölümlerinde eğer listelenecek herhangi bir içerik olmadığını göstermek istiyorsak iki yolu var. Birisi Alert View kullanmak ikincisi de table view’a direk mesaj yazmak. İkincisi her zaman terciğim. Ancak genelde table listesinin hücresine(cell) yazmayı tercih ediyordum. Bu da bir çok gereksiz koşul koymamı sağlıyordu. Bugün daha güzelini keşfettim. Table listesinin üzerine başka bir view eklemek ve dolu-boş koşuna göre göster-gizle yapmak. Kulağa mantıklı geliyor değil mi ? Yani “Talk is cheap show me your code.” diyenlerdenseniz aşağıya göz atabilirsiniz.
viewDidLoad:


- (void)viewDidLoad {
    [super viewDidLoad];

    // Global declared 'noMatchedView'
    noMatchedView = [[UIView alloc] initWithFrame:self.view.frame];
    noMatchedView.backgroundColor = [UIColor whiteColor];
    
    noMatchedLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
    noMatchedLabel.font = [UIFont boldSystemFontOfSize:18];
    noMatchedLabel.numberOfLines = 1;
    noMatchedLabel.shadowColor = [UIColor lightTextColor];
    noMatchedLabel.textColor = [UIColor darkGrayColor];
    noMatchedLabel.shadowOffset = CGSizeMake(0, 1);
    noMatchedLabel.backgroundColor = [UIColor clearColor];
    noMatchedLabel.text = @"Takas edeceğiniz ürününüz yok.";
    noMatchedLabel.textAlignment = NSTextAlignmentCenter;
    noMatchedView.hidden = YES;
    [noMatchedView addSubview:noMatchedLabel];
    [self.tableView insertSubview:noMatchedView belowSubview:self.tableView];
}

daha sonra tableView:numberOfRowsInSection delegate metodunda göster-gizle işlemini yapabiliriz.


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    if(self.items.count == 0) {
        self.tableView.separatorColor = [UIColor clearColor];
        noMatchedView.hidden = NO;
    } else {
        noMatchedView.hidden = YES;
    }
    return self.items.count;
}

Ayrıca aşağıdaki hazır ve gayet güzel olan TableView / CollectionView ile uyumlu bir kütüphane var.
https://github.com/dzenbot/DZNEmptyDataSet

iOS Call dynamic class

iOS projelerinde sıkça table view controller yapılarını kullanırız. Bu yapı geliştiriciye bir çok yeniliği getirdiği gibi aynı zaman da geliştirme sürecini de önemli ölçüde azaltığını düşünüyorum. Bu yazımda da bahsetmek istediğim şey dinamik olarak projemizin package’ında bununan herhangi bir sınıfı tableview’in cell’inin herhangi birine tıkladığında çağırılmasını işleyeceğiz. Örneğin kullanıcı 1. indexe sahip cell’e tıklarsa Class1.m sınıfını çağırmayı göstermeye çalışacağım.

TableViewController’ı oluşturduğunuzu ve tableView:didSelectRowAtIndexPath:indexPath metodunun içerisine aşağıdaki kodu yazalım;


NSString *viewControllerClassName = [NSString stringWithFormat:@"Class%@ViewController", @(indexPath.row + 1)];
Class viewControllerKlass = NSClassFromString(viewControllerClassName);
NSAssert(viewControllerKlass, @"Sınıf tanımsız olmamalı!");
NSAssert([viewControllerKlass isSubclassOfClass:[UIViewController class]], @"Tanımladığınız sınıf UIViewController sınıfına ait olmalı!");

UIViewController *demoViewController = [[viewControllerKlass alloc] initWithNibName:nil bundle:nil];

// belirtilen sınıf package da varsa navigationcontroller'a push et.
if (demoViewController) {
       [self.navigationController pushViewController:demoViewController animated:YES];
}

TableViewController’ımız da 4 adet cell olduğunu varsayarak sınıflarımız sırasıyla ;

Class1ViewController.m
Class2ViewController.m

şeklinde olmalıdır.

My iOS Development Arsenal

Bu yazımda iOS development yaparken geliştirme sürecimi kısaltan ya da güzelleştiren bir kaç eklentiden bahsedeceğim.

KSImageNamed
Programatik olarak oluşturuduğunuz UIImage sınıfına Asset dosyanızda bulunan .png ya da .jpg formatındaki resimleri önizlemenizi sağlıyor. Sadece [UIImage imageNamed:]; şeklinde çalışıyor.

https://github.com/ksuther/KSImageNamed-Xcode

Color Sense for Xcode
UIColor ile oluşturduğumuz renkleri hem önizlememizi hem de RBG şeklinde ayarlamamızı sağlıyor. Ayrıca rengi belirledikten sonra renge tıklayıp Color Picker bile açabiliyorsunuz. Oradan seçtiğiniz herhangi bir renk direk olarak RGB şekilde kodunu otamatik olarak kendisi yazıyor.

https://github.com/omz/ColorSense-for-Xcode

FLEX Inspector
Spark ve Reveal Inspector gibi ios uygulamanızın herhangi bir view’ını seçmenizi üzerinde herhangi bir property varsa görmenizi sağlıyor. FLEX ve DCIntrospect’in faydası diğer desktop inspectorlerdeki gibi Build Phareses’da fazladan işlem yapmanız gerekmiyor.

https://github.com/Flipboard/FLEX

DCIntrospect
Buda FLEX gibi bir inspector alternatik olsun diye paylaştım.

https://github.com/domesticcatsoftware/DCIntrospect

Custom Loader with UIActivityIndicatorView

Eğer loader işlemlerinizde üçüncü parti bir kütüphane kullanmak istemiyorsanız kendiniz bir UIViewController oluşturup custom bir loadar yapabilirsiniz. UIImageView’in animatedImages özelliğini kullanarak sekans sekans görüntüsü alınmış imajları pre-loading şekilde gösterebiliriz. Aşağıdaki bahsettiğim kod tam da bu işe yarıyor.

UIImageView *preloadingImageView = [[UIImageView alloc] init];
preloadingImageView.animationImages = @[@"image_sequence_01.png",@"image_sequence_02.png",@"image_sequence_03.png"];
[self.view addSubview:preloadingImageView];
[preloadingImageView startAnimating];

İsterseniz viewDidload:animated: methodunda bir de arkasına overlay view atarak daha güzel bir hale getirebilirsiniz. Ayrıca diğer sınıflarda da kullananmak isterseniz singleton hale getirebilirsiniz ya da label ekleyebilirsiniz.

iOS saving and reading JSON file

iOS ve OSX ortamında JSON formatlarıyla oynamak diğer dillere göre biraz daha kolay diye düşünüyorum. OSX SDK’in içinde mevcut parserlar mevcut. NSJSONSerialization sınıfı hem JSON dosyalarımızı okumayı hem de üzerinde işlem yapmamızı kolaylaştırıyor. Aşağıda çok basit bir örnek ile mantığını kavramak açısından hem JSON dosyasını veri işlemeyi hem de okumayı göstereceğim. İlk olarak basit bir örnek ile verimizi iOS cihazının Library dizinine hani OS’un sistemine yazalım.

NSMutableArray *topLevelNode = [[] mutableCopy];
NSArray *tempNames = [@"ahmet",@"mehmet",@"veli"];

for(int i = 0; i<tempNames.count; i++) {
     NSMutableDictionary *singleNode = {}.mutableCopy;
     singleNode.name = tempNames[i];
     [topLevelNode addObject:singleNode];
}

NSURL *library = [fileManager URLForDirectory:NSLibraryDirectory
                                         inDomain:NSUserDomainMask
                                appropriateForURL:nil
                                           create:NO
                                            error:nil];

NSURL *jsonFile = [library URLByAppendingPathComponent:@"names.json" isDirectory:NO];

// Eğer manuel olarak oluşturduğumuz JSON dosyası yazılmaya müsaitse yazdırma işlemini yapıyoruz

if([NSJSONSerialization isValidJSONObject:topLevelNode]) {
     NSData *json = [NSJSONSerialization dataWithJSONObject:topLevelNode
                                         options:NSJSONWritingPrettyPrinted
                                         error:nil];
     [json writeToURL:jsonFile atomically:YES];
}

Yukarıda farkettiğiniz üzere iki tane NSURL objesi kullandık. Bunun sebebi ise Apple’ın koyduğu standartlar yüzünden. Eğer iOS cihazlarda dizine ulaşmak istiyor isek yani üzerinde işlem yapmak istiyor ise NSURL sınıfı kullanmak zorundayız.

Okumayı yazmayı bitirdik. Şimdi de yazdığımızı okuyalım…

NSFileManager *read_FileManager = [NSFileManager defaultManager];
    
    NSURL *read_LibraryDocument = [read_FileManager URLForDirectory:NSLibraryDirectory
                                                 inDomain:NSUserDomainMask
                                        appropriateForURL:nil
                                                   create:NO
                                                    error:nil];
    NSURL *read_JsonFile = [read_LibraryDocument URLByAppendingPathComponent:@"names.json" isDirectory:NO];
    NSData *read_JsonData = [NSData dataWithContentsOfURL:read_JsonFile];
    
    NSArray *videoGameJSON = [NSJSONSerialization JSONObjectWithData:read_JsonData
                                                             options:NSJSONReadingMutableContainers
                                                               error:nil];
    // parse it for videoGames array
    NSMutableArray *names = @[].mutableCopy;
    
    for(NSDictionary *jsonNode in names) {
        
        CustomModel *customModel = [[CustomModel alloc] init];
        customModel.name = jsonNode[@"name"];
        [videoGameReviews addObject:customModel];
    }

Yukarıda da yazdırma ile ilgili hemen hemen aynı işlemi yaptık. Sadece ben daha sonradan veri eklenebilmesi için bir boş NSObject model oluşturup onun içine verdim “name” attributunu.