Latest 1.1
Homepage https://github.com/dodikk/ObjcScopedGuard
License BSD
Platforms ios 6.0, requires ARC
Frameworks Foundation
Authors

Carthage Support
Pod Version
Pod Platform

What is ObjcScopedGuard ?

It is a class in ObjectiveC++ that uses blocks to release resources.
A scoped guard executes the block in its C++ destructor and ensures correct resource management even if an exception has been thrown.

This class introduces the RAII idiom to the world of iOS developers.

License : BSD

Why ObjcScopedGuard ?

Correct manuall resource handling resources is a hard work and is the main source of bugs.

using namespace ::std;

void bad(const char* p)
{
    FILE* fh = fopen(p,"r"); // acquire

    // use f
    if ( someCondition )
    {
        // Oops! Looks like we are missing the fclose() statement and leaking the resource
        return;
    }

    f(); // OOPS! Exceptions can be thrown.
    fclose(fh); // release
    cout << "fclose() called" << endl;
}

The scoped guard idiom can be treated as an autorelease or @autoreleasepool statement for low level resources. Unlike autorelease the resource is disposed at the moment the function exits. Moreover, it works both for return and for @throw exteption cases.

The ObjcScopedGuard class uses Objective-C blocks for easiy integration with existing legacy code.

How to use ObjcScopedGuard ?

This class should be used to dispose resources that are not managed by ARC including :

  1. File and stream handles
  2. dispatch_source_t instances
  3. sqlite3 handles
  4. CoreFoundation objects (those disposed by CFRelease)

The code from the previous section can be rewritten in the resource safe and scalable manner :

using namespace ::std;
using namespace ::Utils;

void good(const char* p)
{
   FILE* fh = fopen(p,"r"); // acquire

    // the block to perform cleanup actions
    GuardCallbackBlock releaseBlock_ = ^void( void )
    {
       cout << "fclose() called" << endl;
       ::fclose( fh ); // release
    };

    // creating a guard
    ObjcScopedGuard guard( releaseBlock_ );

    // use f
    if ( someCondition )
    {
        // Now the scoped guard will release the resource
        return;
    }

    f(); // OOPS! Exceptions can be thrown.

    // Fclose should not be called explicitly since the 
    /*
    fclose(fh); // release
    cout << "fclose() called" << endl;
    */
}

One More Thing…

Sometimes objects should live longer than the function scope and integrated with the Cocoa autoreleasepool system. Meaning, it should be possible to retain and release the guard. The ObjcReferendeCountGuard class which is a part of this library solves the mentioned problem.

using namespace ::std;
using namespace ::Utils;

void good_retain_release(const char* p, id<GuardHolderProtocol> guardHolder)
{
   FILE* fh = fopen(p,"r"); // acquire

    // the block to perform cleanup actions
    GuardCallbackBlock releaseBlock_ = ^void( void )
    {
       cout << "fclose() called" << endl;
       ::fclose( fh ); // release
    };

    // creating a guard and storing a strong reference to it
    guardHolder.guard = [ [ ObjcReferendeCountGuard alloc ] initWithBlock: releaseBlock_ ]; 

    // use f
    if ( someCondition )
    {
        // Now the scoped guard will release the resource
        return;
    }

    f(); // OOPS! Exceptions can be thrown.

    // Fclose should not be called explicitly since the 
    /*
    fclose(fh); // release
    cout << "fclose() called" << endl;
    */
}

Bibliography

Some code examples have been taken from the "Resource Acquisition is Initialization" presentation by Andrey Dankevich.

Bitdeli Badge

Latest podspec

{
    "name": "ObjcScopedGuard",
    "version": "1.1",
    "summary": "A class in Objective-C++ to effectively manage critical resources such as files, streams, sockets.",
    "description": "A class in Objective-C++ to effectively manage critical resources such as files, streams, sockets. It uses Objective-C blocks to hold cleanup actions. The resource gets disposed once the function exits. You won't forget to close your file or dismiss the operation queue anymore.",
    "homepage": "https://github.com/dodikk/ObjcScopedGuard",
    "license": {
        "type": "BSD",
        "file": "License-BSD.txt"
    },
    "source": {
        "git": "https://github.com/dodikk/ObjcScopedGuard.git",
        "tag": "v1.1"
    },
    "authors": {
        "Alexander Dodatko": "[email protected]"
    },
    "platforms": {
        "ios": "6.0"
    },
    "requires_arc": true,
    "header_mappings_dir": "ObjcScopedGuard/ObjcScopedGuard",
    "source_files": "ObjcScopedGuard/ObjcScopedGuard/**/*.{c,cpp,mm,m,h,hpp}",
    "prefix_header_file": "ObjcScopedGuard/ObjcScopedGuard/ObjcScopedGuard-Prefix.pch",
    "frameworks": "Foundation",
    "libraries": [
        "c++",
        "stdc++"
    ]
}

Pin It on Pinterest

Share This