ObjcScopedGuard 1.1

ObjcScopedGuard 1.1

测试已测试
语言语言 Objective C++Objective C++
许可 BSD
发布最后发布2014年12月

Alexander Dodatko 维护。



  • 作者
  • Alexander Dodatko

什么是 ObjcScopedGuard ?

这是一个 ObjectiveC++ 类,使用块来释放资源。范围守护会在其 C++ 析构函数中执行块,并确保即使在抛出异常的情况下也能正确管理资源。

这个类将 RAII 习语引入了 iOS 开发者的世界。

License : BSD

为什么使用 ObjcScopedGuard ?

正确手动管理资源是一项艰苦的工作,也是错误的主要来源。

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;
}

范围守护习语可以被看作是一个低级资源的 autorelease@autoreleasepool 语句。与 autorelease 不同,资源在 函数退出时 被释放。此外,它同时也适用于 返回@throw 异常 的情况。

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

如何使用 ObjcScopedGuard ?

应该使用这个类来处理没有由 ARC 管理的资源,包括

  1. 文件 处理
  2. dispatch_source_t 实例
  3. ** sqlite3 ** 处理
  4. CoreFoundation 对象(由 CFRelease 处理的项目)

可以将上一节的代码以资源安全可扩展的方式重写

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;
    */
}

还有一件事...

有时候对象应该比函数范围的生命周期更长,并集成到 Cocoa autoreleasepool 系统 中。这意味着,应该能够对守护进行 保留释放。本库中的 ObjcReferenceCountGuard 类解决了上述问题。

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;
    */
}

参考书目

一些 代码示例 来自 Andrey Dankevich 的 "Resource Acquisition is Initialization" 演示文稿

Bitdeli Badge