zoukankan      html  css  js  c++  java
  • IOS6学习笔记(二)

    四.使用关联引用为分类添加数据

      虽然不能在分类中创建实例变量,但是可以创建关联引用(associative reference)。通过关联引用,你可以向任何对象中添加键-值(key-value)数据。

      假如有一个Person类,这个person类可能会被用在其他程序中,有些电子邮件地址(emailAddress)这个字段是有意义的,有些时候这个字段是没有用的。一个比较好的解决方案就是使用分类为Person类添加一个名为emailAddress的属性,这样可以避免不需要emailAddress时的开销。或许Person类并不是你写的,改类的维护者也不会为你添加这个属性。这种情况下,要怎么解决问题看?首先看一下Person类的定义:

      @interface Person:NSObject

      @property (nonatomic, readwrite, copy) NSString *name;

      @end;

      @implementation Person

      @end

      现在使用关联引用在分类中添加一个emailAddress属性:

      #import<objc/runtime.h>

      @interface Person(EmailAddress)

      @property (nonatomic, readwrite, copy) NSString *emailAddress;

      @end

      @implementation Person (EmailAddress)

      static char emailAddressKey;

      - (NSString *)emailAddress{

        return objc_getAssociatedObject(self, &emailAddressKey);

      }

      - (void)setEmailAddress:(NSString *)emailAddress{

        objc_setAssociatedObject(self, &emailAddressKey,emailAddress,OBJC_ASSOCIATION_COPY);

      }

      @end

      可以看出,关联引用是基于键(key)的内存地址的,而不是键的值。在emailAddressKey中储存的内容并不重要,但是它需要一个唯一地址,所以通常使用一个未赋值的static char 作为键。

      如果要在警告面板中关联一个对象,使用关联引用是一个非常好的方式。例:

    #import "ViewController.h"

    #import <objc/runtime.h>

     

    @implementation ViewController

     

    static const char kRepresentedObject;

     

    - (IBAction)doSomething:(id)sender {

      UIAlertView *alert = [[UIAlertViewalloc]

                            initWithTitle:@"Alert" message:nil

                            delegate:self

                            cancelButtonTitle:@"OK"

                            otherButtonTitles:nil];

      objc_setAssociatedObject(alert, &kRepresentedObject

                               sender,

                               OBJC_ASSOCIATION_RETAIN_NONATOMIC);

      [alert show];

      

    }

     

    - (void)alertView:(UIAlertView *)alertView 

    clickedButtonAtIndex:(NSInteger)buttonIndex {

      UIButton *sender = objc_getAssociatedObject(alertView, 

                                                  &kRepresentedObject);

      self.buttonLabel.text = [[sender titleLabel] text];

    }

    @end

     

    五.类扩展(class extension)

      类扩展的声明方式跟分类很像,只不过括号内的名字是空的:

      @interface MyObject()

      - (void)doSomething;

      @end

      类扩展是在.m文件中声明私有方法的一个很棒的方式。不同于分类,在类扩展中声明的方法与在类中声明的方法是完全一致的,这些方法必须全部实现(分类的方法不必全都实现),且在编译时被添加到类中,而分类是在运行时添加。在类扩展中也可以声明合成属性。

    六.协议

      协议跟类一样可以继承。协议应该总是继承<NSObject>,就像类总是继承NSObject一样。委托协议(delegate protocol)的第一个参数总是委托对象。正是因此,一个委托才能管理多个委托对象。比如,一个控制器就可以作为多个UIAlertView实例的委托来使用。注意在委托对象之外是否还有其他参数,这对命名约定有一定影响。如果没有参数,类名应该最后出现(numberOfSectionsInTableView:);如果有其他参数,类名要首先出现,作为它自身的参数(tableView:numberOfRowsInSection:)。

      创建协议之后,通常还需要一个属性以便于操作它,通常使用id<Protocol>的方式来声明:

      @property(nonatomic, readwrite, weak) id<MyDelegate> delegate;

      这表示“与MyDelegate协议相容的任何对象”。同事使用类和协议声明一个属性也是可以的,而且可以使用多个协议:

      @property(nonatomic, readwrite, weak) MyClass *<MyDelegate,UITableViewDelegate> delegate;

      这个属性声明是说delegate必须是MyClass或其子类的对象,而且必须同时与<MyDelegate>和<UITableViewDelegate>协议相容。

     

    六.单例

      建议使用Grand Center Dispatch(CCD):

      + (MYSingleton *)sharedSingleton{

        static dispatch_once_t pred;

        static MYSingleton *instance = nil;

        dispatch_once(&pred, ^{instance = [[self alloc] init];});

        return instance;

      }

      这样编写方便、快速,而且线程安全。其他方法要在+sharedSingleton中添加一个@synchronize以达到线程安全的目的,但是这种做法在每次调用+sharedSingleton时都会导致性能显著下降。另外,还可以使用+initialize,但使用GCD的方法最简单。

      强制执行单例:

      + (MYSingleton *)sharedSingleton{

        static dispatch_once_t pred;

        static MYSingleton *instance = nil;

        dispatch_once(&pred, ^{instance = [[self alloc] init];});

        return instance;

      }

      - (id)init{

        //禁用调用-init或new

        NSAssert(NO, @"Cannot create instance of Singleton");

        //在这里,你可以返回nil或[self initSingleton],由你来决定是返回nil还是返回[self...]

        return nil;

       }

      //真正的(私有)init方法

      - (id)initSingleton{

        self = [super init];

        if(self){

          //初始化代码

        }

        return self;

      }

     

  • 相关阅读:
    2017.10.17笔记
    鼠标移入移出方向判断
    12.14 css3
    百叶窗 蒙版 图层
    banner轮播
    12.13
    12.11 jq基础
    11.30 AJAX
    11.28 Window事件 iframe操作
    11.28.cookie
  • 原文地址:https://www.cnblogs.com/jay-dong/p/3152927.html
Copyright © 2011-2022 走看看