Category: iOS

  • Objective-C Fundamentals & Nuances

    You may write Objective-C code for 1-2 years, but still you may not know some fundamentals and nuances, that this programming language has. This may be a reason, why you fail to get a good job. Here I will post some important notes, that every iOS developer should understand though they may not be used often practically. This is taken from Cocoa fundamentals guide:

    1.
    Objective-C, the development language for Cocoa, is thoroughly object-oriented too, despite its grounding in ANSI C. It provides runtime support for message dispatch and specifies syntactical conventions for defining new classes. Objective-C supports most of the abstractions and mechanisms found in other object-oriented languages such as C++ and Java. These include inheritance, encapsulation, reusability, and polymorphism.

    2.
    But Objective-C is different from these other object-oriented languages, often in important ways. For example, Objective-C, unlike C++, doesn’t allow operator overloading, templates, or multiple inheritance.

    3.
    Every Objective-C object hides a data structure whose first member—or instance variable—is the isa pointer. (Most remaining members are defined by the object’s class and superclasses.) The isa pointer, as the name suggests, points to the object’s class, which is an object in its own right (see Figure 2-1) and is compiled from the class definition. The class object maintains a dispatch table consisting essentially of pointers to the methods it implements; it also holds a pointer to its superclass, which has its own dispatch table and superclass pointer. Through this chain of references, an object has access to the method implementations of its class and all its superclasses (as well as all inherited public and protected instance variables). The isa pointer is critical to the message-dispatch mechanism and to the dynamism of Cocoa objects.

    4.
    Objective-C is a very dynamic language. Its dynamism frees a program from compile-time and link-time constraints and shifts much of the responsibility for symbol resolution to runtime, when the user is in control. Objective-C is more dynamic than other programming languages because its dynamism springs from three sources:

    Dynamic typing—determining the class of an object at runtime

    Dynamic binding—determining the method to invoke at runtime

    Dynamic loading—adding new modules to a program at runtime

    5.
    For dynamic typing, Objective-C introduces the id data type, which can represent any Cocoa object. The id data type makes it possible to substitute any type of object at runtime. You can thereby let runtime factors dictate what kind of object is to be used in your code. Dynamic typing permits associations between objects to be determined at runtime rather than forcing them to be encoded in a static design. Static type checking at compile time may ensure stricter data integrity, but in exchange for that stricter integrity, dynamic typing gives your program much greater flexibility. And through object introspection (for example, asking a dynamically typed, anonymous object what its class is) you can still verify the type of an object at runtime and thus validate its suitability for a particular operation. (Of course, you can always statically check the types of objects when you need to.)

    6.
    Dynamic typing gives substance to dynamic binding, the second kind of dynamism in Objective-C. Just as dynamic typing defers the resolution of an object’s class membership until runtime, dynamic binding defers the decision of which method to invoke until runtime. Method invocations are not bound to code during compilation; they are bound only when a message is actually delivered. With both dynamic typing and dynamic binding, you can obtain different results in your code each time you execute it. Runtime factors determine which receiver is chosen and which method is invoked.

    The runtime’s message-dispatch machinery enables dynamic binding. When you send a message to a dynamically typed object, the runtime system uses the receiver’s isa pointer to locate the object’s class, and from there the method implementation to invoke. The method is dynamically bound to the message. And you don’t have to do anything special in your Objective-C code to reap the benefits of dynamic binding. It happens routinely and transparently every time you send a message, especially one to a dynamically typed object.

    7.
    Dynamic loading, the final type of dynamism, is a feature of Cocoa that depends on Objective-C for runtime support. With dynamic loading, a Cocoa program can load executable code and resources as they’re needed instead of having to load all program components at launch time. The executable code (which is linked prior to loading) often contains new classes that become integrated into the runtime image of the program. Both code and localized resources (including nib files) are packaged in bundles and are explicitly loaded with methods defined in Foundation’s NSBundle class.

    This “lazy-loading” of program code and resources improves overall performance by placing lower memory demands on the system. Even more importantly, dynamic loading makes applications extensible. You can devise a plug-in architecture for your application that allows you and other developers to customize it with additional modules that the application can dynamically load months or even years after the application is released. If the design is right, the classes in these modules will not clash with the classes already in place because each class encapsulates its implementation and has its own namespace.

  • “Open In…” in iOS apps

    I have added “Open in …” to my iOS app and answered a corresponding question in StackOverflow here.

  • Check if folder exists and create it, if it doesn’t in iOS

    It is interesting and quite uncommon that to check weather a folder exists, you should create a bool reference and pass it to the method fileExistsAtPath. This is a sample getter for a folderPath property, that I created. It can be used in various projects. It creates a folder in Documents folder of your app. Change amp to &.

    - (NSString *)folderPath
    {
        if (! _folderPath) {
            NSString *folderName = @"YourFolderName";
            NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectoryPath = [documentPaths objectAtIndex:0];
            _folderPath = [documentsDirectoryPath stringByAppendingPathComponent:folderName];
    
            // if folder doesn't exist, create it
            NSError *error = nil;
            NSFileManager *fileManager = [NSFileManager defaultManager];
            BOOL isDir;
            if (! [fileManager fileExistsAtPath:_folderPath isDirectory:&isDir]) {
                BOOL success = [fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:NO attributes:nil error:&error];
                if (!success || error) {
                    NSLog(@"Error: %@", [error localizedDescription]);
                }
                NSAssert(success, @"Failed to create folder at path:%@", _folderPath);
            }
        }
    
        return _folderPath;
    }

    Reference to StackOverflow

  • Using NSRegularExpression with NSAttributedString

    I think, it is a very convenient way to use regular expressions to find a range for applying attributes to NSAttributedString. This is how I did it:

        NSMutableAttributedString *goodText = [[NSMutableAttributedString alloc] initWithString:articleText];
    
        NSRange range = [articleText rangeOfString:@"\\[.+?\\]" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
        if (range.location != NSNotFound) {
            [goodText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Georgia" size:16] range:range];
            [goodText addAttribute:NSForegroundColorAttributeName value:[UIColor brownColor] range:range];
        }
    
        NSString *regEx = [NSString stringWithFormat:@"%@.+?\\s", [self.article.titleText substringToIndex:0]];
        range = [articleText rangeOfString:regEx options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
        if (range.location != NSNotFound) {
            [goodText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Georgia-Bold" size:20] range:range];
            [goodText addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:range];
        }
    
        [self.textView setAttributedText:goodText];

    I was searching for a list of available attributes and didn’t find them in a class reference’s first page. So I decided to post here information on that.

    Attributed strings support the following standard attributes for text.

        NSString *NSFontAttributeName;
        NSString *NSParagraphStyleAttributeName;
        NSString *NSForegroundColorAttributeName;
        NSString *NSUnderlineStyleAttributeName;
        NSString *NSSuperscriptAttributeName;
        NSString *NSBackgroundColorAttributeName;
        NSString *NSAttachmentAttributeName;
        NSString *NSLigatureAttributeName;
        NSString *NSBaselineOffsetAttributeName;
        NSString *NSKernAttributeName;
        NSString *NSLinkAttributeName;
        NSString *NSStrokeWidthAttributeName;
        NSString *NSStrokeColorAttributeName;
        NSString *NSUnderlineColorAttributeName;
        NSString *NSStrikethroughStyleAttributeName;
        NSString *NSStrikethroughColorAttributeName;
        NSString *NSShadowAttributeName;
        NSString *NSObliquenessAttributeName;
        NSString *NSExpansionAttributeName;
        NSString *NSCursorAttributeName;
        NSString *NSToolTipAttributeName;
        NSString *NSMarkedClauseSegmentAttributeName;
        NSString *NSWritingDirectionAttributeName;
        NSString *NSVerticalGlyphFormAttributeName;
        NSString *NSTextAlternativesAttributeName;

    Standart Attributes

    NSAttributedString programming guide

    A full class reference is here

     

  • Generating random BOOL and int values in Objective C

    I had to generate random BOOL value to create a random error condition in my app and to test, how this error is handled.

    So this is how I did it:

    srand(time(0));
    int randomval = rand() % 2;
    apiCall.shouldFailToLoad = (BOOL)randomval;
    NSLog(@"Should fail to load:%d", apiCall.shouldFailToLoad);
    

    We create a seed from current time moment for a rand function. Then we get a random number and a module from division by 2. It can be only 0 or 1. Then we tell our apiCall object to get a BOOL value, which tells it to fail sometimes.

    To create a random integer value use this:

    arc4random_uniform(upper_bound)
    

    It will return a uniformly distributed random number less than upper_bound. arc4random_uniform() is recommended over constructions like “arc4random() % upper_bound” as it avoids “modulo bias” when the upper bound is not a power of two.

    Reference: http://stackoverflow.com/questions/160890/generating-random-numbers-in-objective-c

  • 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.