14 Temmuz 2015 Salı

Attributed text kullanırken TextView'ın toplam metin yüksekliğini hesaplama

Ne yaptıysam textView.contentSize.height hep yanlış değerler geliyordu. Biyerlerden aşağıdaki kodu buldum ve şıkır şıkır çalışıyor.

- (CGFloat)measureHeightOfUITextView:(UITextView *)aTextView
{
    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
    {
        // This is the code for iOS 7. contentSize no longer returns the correct value, so
        // we have to calculate it.
        //
        // This is partly borrowed from HPGrowingTextView, but I've replaced the
        // magic fudge factors with the calculated values (having worked out where
        // they came from)
        
        CGRect frame = aTextView.bounds;
        
        // Take account of the padding added around the text.
        
        UIEdgeInsets textContainerInsets = aTextView.textContainerInset;
        UIEdgeInsets contentInsets = aTextView.contentInset;
        
        CGFloat leftRightPadding = textContainerInsets.left + textContainerInsets.right + aTextView.textContainer.lineFragmentPadding * 2 + contentInsets.left + contentInsets.right;
        CGFloat topBottomPadding = textContainerInsets.top + textContainerInsets.bottom + contentInsets.top + contentInsets.bottom;
        
        frame.size.width -= leftRightPadding;
        frame.size.height -= topBottomPadding;
        
        NSString *textToMeasure = aTextView.text;
        if ([textToMeasure hasSuffix:@"\n"])
        {
            textToMeasure = [NSString stringWithFormat:@"%@-", aTextView.text];
        }
        
        // NSString class method: boundingRectWithSize:options:attributes:context is
        // available only on ios7.0 sdk.
        
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
        
        NSDictionary *attributes = @{ NSFontAttributeName: aTextView.font, NSParagraphStyleAttributeName : paragraphStyle };
        
        CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:attributes
                                                  context:nil];
        
        CGFloat measuredHeight = ceilf(CGRectGetHeight(size) + topBottomPadding);
        return measuredHeight;
    }
    else
    {
        return aTextView.contentSize.height;
    }
}

21 Haziran 2015 Pazar

FMDB kullanırken Vacuum kullanımı

Diyelim ki oyununuzun ipa ile gelen paketinin içinde bir veritabanı var ve bu veritabanını uygulamanın kullanımı sırasında güncelliyorsunuz. Bu durumda veritabanı dosyasını modifiye edilebilir hale gelmesi için documents klasörüne kopyalamanız gerekiyor. Kopyalamayı yaptınız diyelim. Bu kopyalamadan sonra bazı tabloları boşaltıp uygulamanın paketi içinden gelen veritabanı dosyasındaki elemanlarla rastgele bir sırada karıştırırarak yeniden dolduruyorsanız "vacuum" komutuna ihtiyacınız vardır. Tüm veritabanlarında genellikle bir kayıt silindiğinde aslında o kayıt veritabanından fiziksel olarak silinmez sadece silinmiştir diye işaretlenir. Bu mantıksal silinmiş kayıtları fiziksel olarak ta silmek için genellikle veritabanına bakım işlemi gerçekleştirirsiniz. Bu işlem sırasında boş bir veritabanı geçici olarak oluştulup içine orjinal veritabanındaki mantıksal olarak mevcut bilgiler aktırılır. Sonra orjinal veritabanı fiziksel olarak silinir ve yerine yeni oluşturulan veritabanı aynı dosya adıyla kopyalanıp kullanılmaya başlanır. sqlite'ta bu işlem için "vacuum" denilen bir komut var. Bu komutu executeUpdate komutuyla çalıştırırsanız veritabanındaki mantıksal kayıtlar fiziksel olarak silinmektedir. Bu ne işe mi yarar, veritabanı dosyanızın boyutuna bağlı olarak hem dosya boyutunuz küçülür hem de veritabanı üzerindeki işlem hızlarınız artabilir. Sevgiler.

FMDB kullanırken garip hatalar

Siz de FMDB kullanırken ResultSet oluştururken garip garip hatalar alıyorsanız sebebi integer değerler olabilir. FMDatabase tipinden bir obje oluşturduysanız ve bu objenin executeQuery veye executeUpdate'ini kullanıyorsanız genellikle ? ile parametreleri paslarsınız. Fakat bu pasladığınız parametreler malesef mutlaka reference type olmalı. Yani bir value type olan int tipinde bir değişkeni query veya update cümlesine son parametre olarak eklerseniz garip bi hata ile karşılaşıyorsunuz. Çözümü int değerinizi parametre olarak verirken bir reference type olan NSNumber'a çevirmek.

[targetDatabase executeUpdate:@"insert into GameItems (Name, PictureFileName, IsCompleted, ItemIndex) values (?,?,?,?)",
                 name,
                 pictureFileName,
                 isCompleted,
                 itemIndex];


bu üstteki kod kırmızı ile işaretli değişken yüzünden hata vermektedir. Çözüm ise şu şekilde

[targetDatabase executeUpdate:@"insert into GameItems (Name, PictureFileName, IsCompleted, ItemIndex) values (?,?,?,?)",
                 name,
                 pictureFileName,
                 isCompleted,
                 [NSNumber numberWithInt:itemIndex]];


Umarım işinize yarar. Sevgiler.