美文网首页
52Effective总结待续

52Effective总结待续

作者: 不明之人 | 来源:发表于2016-06-09 00:59 被阅读34次
第二条少用#import,多用@class,向前声明,将引入头文件的时机尽量延后,只有在需要时才引入。可以减少编译时间和防止循环引用。
  .h文件用@class MyView;

# import <UIKit/UIKit.h>
@classMyView;
@interfaceViewController : UIViewController
- (void)sendMyView:(MyView*)mine;
@end

   .m文件用#import"MyView.h",因为需要MyView的方法,否则会报错

#import "ViewController.h"
#import "MyView.h"
@interface ViewController()
@end

@implementation ViewController
- (void)viewDidLoad{
   [super viewDidLoad];
   MyView *myview = [[MyView alloc]init];
   myview.title =@"这是一个view";
   [self sendMyView:myview];
}
- (void)sendMyView:(MyView *)mine
{
}

第三条多用字面量语法,以下两种字符串的初始化方法是等价的,但是第二种会更加简洁,本书建议用第二种方法,我觉得根据实际情况来操作,如果是数组或者是字典的初始化我会选择用第一种方法,因为我不希望程序在遇到异常值的时候奔溃。
  字符串初始化方法

NSString *str = [NSString stringWithFormat:@"abc"];
NSString *str = @"abc";

  类似的初始化方法中还有数组字典等,但是元素不能为nil,否则会奔溃。

NSArray *array = @[@"小明",@"小东",@"小红"];
NSDictionary *dictionary = @{
   @"firstName":@"wu",
   @"lastName":@"qingdao",
   @"age":@10
};
NSString *str = nil;
NSArray *array = @[@"小明",@"小东",str];(会奔溃)
NSArray *array = [NSArray arrayWithObjects:@"小明",@"小东",str,nil];(不会奔溃)

第四条多用类型常量,少用#define

如果只是在本类中使用,那么就在.m文件中定义即可,而且一般以小写字母“k”开头,不管是类型常量还是宏。

  如果用宏定义,那么有可能被替换,比如在一个类中定义kAnimationDuration为0.3,另一个类中定义kAnimationDuration为0.4

#define kAnimationDuration 0.3

  类型常量kAnimationDuration附带类型信息,并且试图修改kAnimationDuration的值的时候会报错   

static const NSTimeIntervalkAnimationDuration = 0.3;

如果打算把这个常量公开,也就是其他类里面也能用到这个常量,那就应该如下定义(extern关键字),请注意“对象常量”(如NSString)和“一般常量”(如NSInterger)写法上的区分。

#import <UIKit/UIKit.h>
extern const NSTimeInterval XJXAnimationDuration;
extern NSString*constXJXMyName;
@interface MyView : UIView
@end

#import "MyView.h"
@implementation MyView
NSTimeInterval const XJXAnimationDuration=0.3;
NSString*const XJXMyName = @"xiao";
@end

第五条 二进制枚举可以减少定义的元素
 //枚举值                                     二进制        十进制

 NOONE    =0 //没人                         00000000        0

 WORKER   =1<<0, //工人                     00000001        1

 DESINGER =1<<1, //设计师                   00000010         2

 MANAGER  =WORKER | DESINGER,//经理         00000011         3

 FINANCIAL =1<<2     //财务                 00000100       4

 BOSS     =FINANCIAL | MANAFGER,//老板      00000111         7

 

 任意两个二进制数,两两按位"或"后得到的数据都是唯一的,比如 WORKER | DESINGER.最后得到的二进制数是00000011。(NOONE除外,因为它与任何数按位"或"后都是,那个数本身)

 所以二进制来表示枚举值的优势是用更少的数据,可以表达更多的状态。所以我们也可以这样定义:

 //枚举值                          二进制     十进制

 NOONE    =0         //没人     00000000    0

 WORKER   =1<<0,     //工人     00000001    1

 DESINGER =1<<1,    //设计师    00000010    2

 FINANCIAL =1<<2     //财务       00000100    4

 

 那如果 return WORKER | DESINGER; 就表示这个人是经理

 如果  return WORKER | DESINGER| FINANCIAL; 就表示这个人是老板。

例子:

#import "ViewController.h"

typedef NS_ENUM(NSUInteger,PostStyle){
  //枚举值            二进制    十进制
  NOONE =0, //没人       00000000    0
  WORKER =1<<0, //工人    00000001    1
  DESINGER =1<<1, //设计师   00000010    2
  FINANCIAL =1<<2 //财务    00000100    4
};

@interfaceViewController (){
  PostStyle style;
}
@end

@implementationViewController
- (PostStyle)Boss
{
  return WORKER | DESINGER| FINANCIAL;
}

- (PostStyle)manager
{
  return WORKER | DESINGER;
}

- (void)viewDidLoad {
   [super viewDidLoad];
   NSLog(@"状态码:老板:%ld,经理:%ld",(unsignedlong)[self Boss],(unsigned long)[selfmanager]);
}

  控制台打印:

**2016-06-1112:55:15.186 52Effective_Objc[1805:434069] ****状态码:老板:****7,****经理:****3****

第七条 对象内部读取数据时,应该通过实例变量(_name)来读取,写入数据用属性来写

懒加载时必须使用实例变量(_name),用self.name会造成死循环
懒加载的优点(其实就是重写 了get方法)

  1不需将对象的实例化写到viewDidLoad,可以简化代码,增强代码的可读性
  
  2对象的实例化在getter方法中,各司其职,降低耦合性
  
  3对系统的内存占用率会减小

#import "XJDropdownMenu.h"
@interface XJDropdownMenu()
@property(nonatomic,weak)UIImageView *containView;
@end
@implementation XJDropdownMenu

  想调用懒加载,就需要用到get方法:self.containView

-(UIImageView *)containView
{
  if (!_containView) { //这里不能用self.containView
     UIImageView *grayBackImageView = [[UIImageView alloc]init];
    _containView = grayBackImageView;
  }
   return _containView;
}

  调用用懒加载

[self.view bringSubviewToFront:self.containView];

第九条 以“类族模式”隐藏实现细节。可以隐藏“抽象基类”的实现细节。
  假如有一个雇员的类(XJEmployee)。它的初始化方法

+ (XJEmployee*)employeeWithType:(EmployeeType)type;

由type来决定返回的类型。一般来说我们会这样写:

typedef NS_ENUM(NSUInteger,EmployeeType){
  Developer,
   Desiginer,
   Finance
};

+ (XJEmployee*)employeeWithType:(EmployeeType)type{
   XJEmployee *employee =[[self alloc]init];
   switch (type) {
     case Desiginer:
      //符合Desiginer的一些属性赋值
     break;
    case Developer:
      //符合Developer的一些属性赋值
     break;
     case Finance:
     //符合Finance的一些属性赋值
   break;
    default:
   break;
  }
    return employee;
}

如果使用族类模式,那么用户无需知道实现细节,这些细节交给XJEmployee的基类去实现。

  声明文件

#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger,EmployeeType){
    Developer,
    Desiginer,
    Finance
};

@interfaceXJEmployee : NSObject
@property(nonatomic,copy)NSString*name;
@property(nonatomic,assign)NSUIntegersalary;

+ (XJEmployee*)employeeWithType:(EmployeeType)type;
- (void)doAdaysWork;
@end

  实现文件

#import "XJEmployee.h"
#import "XJDesigner.h"
#import "XJDeveloper.h"
#import "XJFinance.h"

@implementation XJEmployee

+ (XJEmployee*)employeeWithType:(EmployeeType)type{
   switch (type) {
     case Desiginer:
     return[XJDesigner new];
   break;
     case Developer:
     return[XJDeveloper new];
    break;
     case Finance:
     return[XJFinance new];
    break;
   default:
    break;
}
}

- (void)doAdaysWork{
//子类复写这个方法。
}

  其中的一个子类XJEmployee 声明文件

#import "XJEmployee.h"
@interface XJDeveloper : XJEmployee
@end

  实现文件

#import "XJDeveloper.h"
@implementation XJDeveloper
- (void)doAdaysWork
{
  NSLog(@"XJDeveloper");
}
@end

  另:本书提到UIButton也是使用了族类模式,我验证了一下,发现与书中所说的不符。

UIButton*bun = [UIButton buttonWithType:UIButtonTypeContactAdd];
  NSLog(@"UIButtonTypeContactAdd-->%@",bun);
   if([bun isMemberOfClass:[UIButton class]]){
    NSLog(@"bunisMemberOfClass_UIButton");
   }
   if ([bun isKindOfClass:[UIButton class]]){
    NSLog(@"bunisKindOfClass_UIButton");
   }

//控制台打印数据:

**UIButtonTypeContactAdd--><UIButton:0x7fe710d69e60; frame = (0 0; 22 22); opaque = NO; layer = <CALayer:0x7fe710d6a340>>
**
**2016-06-0615:11:28.526 ****关联对象用法****[2148:188055]bun isMemberOfClass_UIButton
**
**2016-06-06 15:11:28.529 ****关联对象用法****[2148:188055] bun isKindOfClass_UIButton

-isMemberOfClass: 是 NSObject 的方法,用以确定某个 NSObject 对象是否是某个类的成员。与之相似的为 -isKindOfClass:,可以用以确定某个对象是否是某个类或其子类的成员。也就是说bun是UIButton的成员。

  验证一下XJEmployee

XJEmployee*ployee = [XJEmployee employeeWithType:Developer];
NSLog(@"Developer-->%@");
  [XJEmployee employeeWithType:Developer]);
   if ([ployee isKindOfClass:[XJEmployee class]]){
    NSLog(@"ployeeisKindOfClass_XJEmployee");
    }
   if ([ployee isMemberOfClass:[XJEmployee class]]){
   NSLog(@"ployeeisMemberOfClass_XJEmployee");
}

  控制台打印数据:

**2016-06-0615:33:38.171 ****关联对象用法****[2230:195652]Developer--><XJDeveloper: 0x7fd8b250e300>
**
**2016-06-06 15:33:38.172 ****关联对象用法****[2230:195652] ployee isKindOfClass_XJEmployee

只打印了ployeeisKindOfClass_XJEmployee.说明ployee不是XJEmployee的成员,而是XJEmployee子类的成员。

相关文章

网友评论

      本文标题:52Effective总结待续

      本文链接:https://www.haomeiwen.com/subject/crgjdttx.html