Blog

  • No known class method for selector reachabilityWithHostName

    I had a really weird experience recently.

    Linker did not link Reachability after I added it as a pod.

        internetReachable = [Reachability reachabilityWithHostName:@"www.google.com"];
    

    In this line compiler was giving error ‘No known class method for selector reachabilityWithHostName:’.

    I tried to readd reachability, tried to clean project, nothing helped. Then I just tried to rewrite this line and it compiled!

        internetReachable = [Reachability reachabilityWithHostname:@"www.google.com"];
    

    And now I understand why it worked. Because my old code was taken from another project with other version of Reachability and selector was with ‘HostName’ but new one is with ‘Hostname’.

    Before rewriting I was checking if Reachability has this method and it seemed to me that it has and I couldn’t understand the problem. It turned out that I didn’t notice this small change in one letter!

  • On XMPPFramework delegate method not being called

    I have wasted some hours trying to understand, why a delegate method is not called and finally found solution. This is pretty common problem, as I’ve seen in the internet during a search, when I tried to resolve it. That is why I decided to write a little post on a solution. It is also pretty common problem, because a thing, that I discovered concerns not only XMPPFramework classes, but also many other similar classes.

    So, the reason of this problem is that most probably your class, that is a delegate for xmppStream and that contains xmppStream is actually released from memory or somehow becomes inactive. This problem occurs because in ARC everything that is created inside a method (and is not an instance variable) is released, when method finishes. And delegate methods cannot be called, that are invoked by some other background process.

    I have a class, called EjabberdRegistrator, it contains XMPPStream as a property and it is a delegate of this XMPPStream.

    @property (strong, nonatomic) XMPPStream *xmppStream;
    
    - (XMPPStream *)xmppStream
    {
        if ( _xmppStream == nil ) {
            
            _xmppStream = [[XMPPStream alloc] init];
            [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
            
        }
        
        return _xmppStream;
    }
    

    This is how I was initializing this class:

    EjabberdRegistrator *ejabberdRegistrator = [[EjabberdRegistrator alloc] init];
    [ejabberdRegistrator registerClientWithInfo:clientInfo delegate:self];
    

    Because ejabberdRegistrator instance is not used anywhere inside a method where it was created, it was released by ARC after method was finished, despite the fact, that xmppStream was still working. That is why xmppStream delegate method was not called.

    After some thoughts I finally discovered this and made my ejabberdRegistrator instance a property and created it like this:

    - (IBAction)signInClicked:(id)sender
    {
        ClientInfo *clientInfo = [[ClientInfo alloc] init];
        clientInfo.roughPhoneNumber = _loginField.text;
        
        self.ejabberdRegistrator = [[EjabberdRegistrator alloc] init];
        [self.ejabberdRegistrator registerClientWithInfo:clientInfo delegate:self];
    }
    

    This worked! So, it is very important to make a class, that is a delegate of some other class, that is contained inside it make persistent from releasing from memory.

    Note that this also can be achieved by creating shared instance of that class using dispatch_once.

  • How to make UIKeyboard not disappear when UIMenuController becomes first responder

    Sometimes we want to not allow UIKeyboard disappear. Look at a chat in “WhatsApp” app. When you click twice on a chat item, keyboard doesn’t disappear. At the same time you see a custom UIMenuController. This is not a default behavior. By default keyboard disappears since to show UIMenuController you need to make your chat item view become first responder.

    The most popular way to make this happen is to use an invisible UITextField or UITextView and make it becomeFirstReposnder after menu is shown.

    But there is a very elegant solution using UIKeyInput Protocol. I found it also at that place.

    Documentation tells

    A subclass of UIResponder can adopt this protocol to implement simple text entry. When instances of this subclass are the first responder, the system keyboard is displayed.
    Only a small subset of the available keyboards and languages are available to classes that adopt this protocol.

    So I decided to use this solution. And it worked perfect! You just need to add this protocol to your class definition. For instance:

    @interface UIBubbleTableViewCell : UITableViewCell 
    
  • If iOS app crashes before launch every second time

    One of my apps, that I develop started to crush every second time on simulator after I updated XCode Version 4.6.2 and OS X Mountain Lion (OS X 10.8.4). I couldn’t figure out why, because method didFinishLaunchingWithOptions didn’t even start when the crush occured. After some search in the web I found solution here and here.

    These are instructions:
    Open the menu Product -> Scheme -> Edit Scheme, select Run YouAppName.app on the left, tab Info. Then choose GDB instead of LLDB in debugger field.

    The reason of this bug is probably:
    The issue occurs to a process race condition for debugserver. Instead of using GDB, you can alternatively kill your execution, wait a few seconds for the app to wrap up, and then run the next iteration.

  • Floor and Ceil in C – Objective C snippet

    Objective C snippet to understand floor and ceil C functions:

        NSArray *array = @[@(5.0), @(5.3), @(5.5), @(5.7)];
    
        CGFloat a, r;
        
        for (NSNumber *n in array) {
            a = [n floatValue];
            r = ceil(a);
            NSLog(@"Ceil (%.1f) = %.1f", a, r);
            r = ceilf(a);
            NSLog(@"Ceilf (%.1f) = %.1f", a, r);
        }
        
        for (NSNumber *n in array) {
            a = [n floatValue];
            r = floor(a);
            NSLog(@"Floor (%.1f) = %.1f", a, r);
            r = floorf(a);
            NSLog(@"Floorf (%.1f) = %.1f", a, r);
        }
    

    It is interesting, that if you divide for instance ceil(9 / 2) you will get 4. But if you divide ceil(9 / 2.0) you will get 5 as expected. I struggled with this issue a little, while trying to calculate item height dynamically for iPhone 5 and iPhone 3-4 in my UICollectionView this way:

        CGFloat viewHeight = IS_WIDESCREEN ? 568.0 : 480;
        NSInteger numberOfRows = ceil([buttonData count] / 2.0);
        CGFloat itemHeight = (viewHeight - 20.0 - 44.0) / numberOfRows;
    

    where

    #define IS_WIDESCREEN [[UIScreen mainScreen] bounds].size.height >= 568.0
    

    I guess, that when you divide 9/2 you get 4 as a result (integer division). When you divide 9/2.0 you get 4.5 which is “ceiled” correctly.

  • How to get a particular key for object in NSDictionary

    This is how you can get a first key for object (in case it is NSString):

    NSArray *keys = [yourDic allKeysForObject:yourObject];
    NSString *yourKey;
    if ([keys count] > 0) 
       yourKey = keys[0];
    

    Since you may not get a key for some objects, if it is absent.

  • How to switch off UIWebView caching in iOS

    I found how to clear cache, before app starts. Add this in didFinishLaunchingWithOptions:

    [[NSURLCache sharedURLCache] removeAllCachedResponses];

    It is possible to remove Cookies and cache for one request. Read it here.

  • How to make git remember your password

    This is the solution to make it remember password for 100 hours (60 s * 60 min * 100):

    $git config --global credential.helper 'cache --timeout=360000'
    
  • How to add an array to the top of another array in iOS

    I found two good solutions in StackOverflow:

    [existingArray replaceObjectsInRange:NSMakeRange(0,0)
                    withObjectsFromArray:newArray];
    

    And the second one:

    NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange: (NSRange) {0, [newArray count]}];
    [existingArray insertObjects: newArray atIndexes: indexes];
    
  • Get file size using NSFileManager

    To get file size in bytes using NSFileManager do the following:

    NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:_filePath error:nil];
    _size = [attrs fileSize];