(10) [OC 고효율 시리즈] 기존 클래스에서 관련 대상을 사용하여 사용자 정의 데이터를 저장한다

6168 단어
1.연관성이 무엇인가
동적 생성 포인터가 한 대상에서 다른 대상을 가리키고 해당하는'메모리 관리 의미'를 따르는 것을 말한다. 이것은 동적으로 하나의 속성을 추가하는 것과 같다.
2. 관련 유형과 같은 효과의property 속성
연관 유형
같은 @property 속성
OBJC_ASSOCIATION_ASSIGN
assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC
nonatomic, retain
OBJC_ASSOCIATION_COPY_NONATOMIC
nonatomic, copy
OBJC_ASSOCIATION_RETAIN
retain
3. 관련api
연결 객체 설정
 void objc_setAssociatedObject(id object, const void *key, 
 id value, objc_AssociationPolicy policy)

연결 개체 가져오기
id objc_getAssociatedObject(id object, const void *key)

연관 객체 제거
void objc_removeAssociatedObjects(id object)

4. 정적 글로벌 변수를 키로
  • 연결 대상을 설정하는 키는 NSDictionary의 키와 다르다.이것은 용어상 '불투명한 지침' 에 속한다.
  • NSDictionary에서 두 키는 isEqual 방법이 YES로 되돌아오면 두 키가 같다고 여긴다.
  • 여기는 완전히 같아야 한다.

  • 5. 관련 대상을 사용하면 좋은 점이 어디에 있습니까?속성을 확장하려면 하위 클래스를 만들면 되지 않습니까?
    계승적인 방식으로 속성을 확장하면 코드가 침입성을 가진다.OC에서는 단일 상속 모드로 A를 상속하면 B를 상속할 수 없고 또 다른 C도 있다.그래서 어떤 특정한 상황에서는 상속을 사용할 수 없다.
    더 많은 것은 분류 + 관련 방식을 사용하여 이미 존재하는 클래스를 확장하는 것이다.이런 코드는 침입성이 없어서 사용하기에 더욱 간단하고 간편하다.
    6.UIImageView+WebCache에 사용된 연관
    UIImageView + WebCache에서 새 그림을 설정할 때마다 현재 이미지 뷰가 불러오는 프로세스를 취소합니다.이러한 프로세스 대상은 연결된 방식으로 이미지뷰에 동적으로 연결되는 것이다.
    //UIImageView+WebCache.m
    - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
        [self sd_cancelCurrentImageLoad];
        ...
        if (url) {
            __weak UIImageView *wself = self;
            id  operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
               ...
            }];
            [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
        } else {
           ...
        }
    }
    
    - (void)sd_cancelCurrentImageLoad {
        [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"];
    }
    
    //UIView+WebCacheOperation.m
    - (NSMutableDictionary *)operationDictionary {
        NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey);
        if (operations) {
            return operations;
        }
        operations = [NSMutableDictionary dictionary];
        objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        return operations;
    }
    
    - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key {
        [self sd_cancelImageLoadOperationWithKey:key];
        NSMutableDictionary *operationDictionary = [self operationDictionary];
        [operationDictionary setObject:operation forKey:key];
    }
    

    7. 관련을 사용하면 delegate 형식으로 인해 분산된 코드를 Block 형식으로 집중시킬 수 있다.이렇게 하면 가독성이 더욱 강하고 코드가 더욱 간결하다.
    UIactionSheet의 경우
    먼저 관련을 사용하지 않을 때의 코드를 하나 주세요.
    @interface ViewController () 
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
       
    }
    
    - (IBAction)didClickBtn:(UIButton *)btn{
        UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Hellow World" delegate:self cancelButtonTitle:@" hellow" destructiveButtonTitle:@"hellow1" otherButtonTitles:@"hellow2",nil];
        [sheet showInView:self.view];
    }
    
    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
       NSLog(@"  %ld",buttonIndex);
    }
    
    @end
    

    이렇게 actionsheet을 눌렀을 때의 논리와 창설된 코드는 분리되어 있으며 코드가 많을 때 이 프록시 방법은 다른 프록시 방법과 함께 놓으면 가독성이 비교적 떨어진다.또한 UIACtion Sheet을 만들 때마다 다음이 필요합니다.
  • 설정 에이전트
  • 프록시 추가
  • 관련 대리 실현 방법
  • --
    연결을 사용하면 ActionSheet의 관련 논리를 하나의 Tool로 독립할 수 있습니다. 코드는 다음과 같습니다.
    //.m
    static char tool;
    static char sheet;
    
    @interface YXActionSheetTool () 
    @property (nonatomic,copy) void(^callback)(NSInteger clickIndex);
    @property (nonatomic,weak) UIViewController *controller;
    @end
    
    @implementation YXActionSheetTool
    + (void)showWithController:(UIViewController *)controller title:(NSString *)title cancleTitle:(NSString *)cancleTitle destructiveTitle:(NSString *)destructiveTitle otherTitles:(NSArray *)otherTitles callback:(void(^)(NSInteger clickIndex))callback {
        
        UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title delegate:nil cancelButtonTitle:cancleTitle destructiveButtonTitle:destructiveTitle otherButtonTitles:nil];
        for (NSString *otherTitle in otherTitles) {
            [sheet addButtonWithTitle:otherTitle];
        }
        YXActionSheetTool *actionSheetTool = [[YXActionSheetTool alloc] init];
        objc_setAssociatedObject(controller,&tool,actionSheetTool,OBJC_ASSOCIATION_RETAIN_NONATOMIC);// tool 
        objc_setAssociatedObject(actionSheetTool,&sheet,sheet,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        actionSheetTool.callback=callback;
        actionSheetTool.controller =controller;
        sheet.delegate=actionSheetTool;
        [sheet showInView:controller.view];
    }
    
    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
        
        objc_setAssociatedObject(self,&sheet,nil,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        objc_setAssociatedObject(self.controller,&tool,nil,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
        if(self.callback)
         self.callback(buttonIndex);
        
    }
    
    @end
    

    호출 코드는 다음과 같습니다
    
    @interface ViewController () 
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
       
    }
    
    - (IBAction)didClickBtn:(UIButton *)btn{ 
        [YXActionSheetTool showWithController:self title:@"Hellow World" cancleTitle:@" hellow" destructiveTitle:@"hellow1" otherTitles:@[@"hellow2"] callback:^(NSInteger clickIndex) {
            NSLog(@"  %ld",clickIndex);
        }];
    }
    
    @end
    

    이렇게 하면 ui 코드와 논리 코드가 함께 있어 읽기에 편리하다.

    좋은 웹페이지 즐겨찾기