iOS - FAQ 정리(一)

13637 단어

하나.통지하다


통지에 대해 모두가 낯설지 않을 것이다. 이것은 하나의 예로 사건이 발생할 때 일부 대상을 통지하고 우리가 낮은 정도의 결합 상황에서 통신의 목적을 달성하도록 허용하는 것이다.
알림의 이점: 1.코드를 너무 많이 작성하지 않아도 비교적 간단하게 실현할 수 있다.하나의 통지에 대해 여러 대상이 반응할 수 있다. 즉, 통지는 일대다의 형식이라는 것이다
알림의 단점: 1.컴파일링 기간에 알림이 관찰자가 정확하게 처리할 수 있는지 확인하지 않습니다.등록된 객체를 해제하려면 공지 센터에서 등록을 취소해야 합니다. 3.디버그 응용 프로그램에서 추적하기 어렵다 4.통지를 보낸 후 관찰자로부터 어떠한 피드백 정보도 얻을 수 없다
알림의 기본 구현:
- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
    NSLog(@"  - %@",[NSThread currentThread]);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
    NSLog(@"  - %@",[NSThread currentThread]);

}

- (void)test {
    NSLog(@"  - %@",[NSThread currentThread]);
    sleep(3);
}

인쇄 결과:
2017-06-13 16:53:01.040  [24531:3283934]   - {number = 1, name = main}
2017-06-13 16:53:10.334  [24531:3283934]   - {number = 1, name = main}
2017-06-13 16:53:13.335  [24531:3283934]   - {number = 1, name = main}

인쇄 결과 주의: 테스트 방법이 실행된 후에야 완료된 로그를 출력할 수 있습니다.
하위 스레드에서 알림을 보내는 경우
- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
    NSLog(@"  - %@",[NSThread currentThread]);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        
        NSNotification *notification = [NSNotification notificationWithName:@"test"
                                                                     object:nil];
        // NSPostASAP   NSPostNow
        [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostNow];
        NSLog(@"  - %@",[NSThread currentThread]);
        });
}

- (void)test {
    NSLog(@"  - %@",[NSThread currentThread]);
    sleep(3);
}

인쇄 결과:
2017-06-13 17:05:01.133  [25191:3296062]   - {number = 1, name = main}
2017-06-13 17:05:02.423  [25191:3296125]   - {number = 3, name = (null)}
2017-06-13 17:05:05.523  [25191:3296125]   - {number = 3, name = (null)}

결론: 알림을 받는 라인은 알림을 보내는 라인과 같다. 만약에 실제 개발 과정에서 우리는 하위 라인에서 알림을 보낸다. 알림을 받은 후에 UI를 갱신하는 등 작업을 해야 하며 반드시 메인 라인으로 돌아가야 한다.
- (void)viewDidLoad {
    [super viewDidLoad];
     _observe = [[NSNotificationCenter defaultCenter] addObserverForName:@"test" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
       NSLog(@"  - %@",[NSThread currentThread]);
        sleep(3);   
    }];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
        NSLog(@"  - %@",[NSThread currentThread]);
        });
}

인쇄 결과:
2017-06-13 18:21:38.367  [29365:3382047]   - {number = 1, name = main}
2017-06-13 18:21:41.368  [29365:3382100]   - {number = 3, name = (null)}

결론: NSOperationQueue를 사용하면 알림을 받는 라인과 보내는 라인이 다르고 알림을 받는 라인이 주 라인에 있으면 UI를 새로 고칠 수 있다.

둘.Xcode에서 unrecognized selector 오류가 보고된 경우

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    WWPerson *person = [[WWPerson alloc] init];
    [person test];
}
persontest 이 메시지를 보낼 때 runtime 라이브러리는 대상의 isa 지침에 따라 대상이 실제 속하는 클래스를 찾은 다음에 이 클래스의 방법 목록과 부류의 방법 목록에서 해당하는 방법을 찾아 실행한다. 맨 윗부분의 부류에서 상응하는 방법을 찾지 못하면 프로그램이 실행될 때 unrecognized selector sent to의 오류를 보고하고 붕괴된다. 그러나 그 전에objc가 실행될 때 프로그램 충돌을 피할 수 있는 세 번의 기회를 제공합니다.
  • Method resolution objc가 실행될 때 호출+resolveInstanceMethod: 또는 +resolveClassMethod:를 사용하면 프로그램이 붕괴되지 않도록 함수를 제공할 수 있습니다. 여기에 함수를 추가하면 시스템은 메시지 발송 과정을 다시 시작하고 그렇지 않으면 다음 메시지로 이동합니다.
  • + (BOOL)resolveInstanceMethod:(SEL)sel {
        if (sel == NSSelectorFromString(@"test")) {
            /**
              class:  
              SEL:  
              IMP:   =>   =>   =>  
              type:  :void v ,id @ ,SEL : 
             */
            class_addMethod(self, sel, (IMP)test, "v@:@");
            return YES;
        }else {
            return [super resolveClassMethod:sel];
        }
    }
    
    void test(id self, SEL _cmd, NSNumber *meter) {
        NSLog(@"  - WWPerson");
    }
    

    2. Fast forwarding 만약에 목표 대상이 -forwardingTargetForSelector: 방법을 실현했다면runtime는 이 방법을 사용해서 우리에게 이 메시지를 다른 대상에게 전달할 기회를 주었다. 이 방법의 반환 값nilself만 아니면 전체 메시지의 발송 과정이 다시 시작될 것이다. 이때 발송 대상은 우리가 되돌아오는 이 대상이 되고 그렇지 않으면 다음 단계로 넘어갈 것이다.
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        WWTarget *target = [[WWTarget alloc] init];
        if ([target respondsToSelector:aSelector]) {
            return target; //  WWTarget test 
        }else {
            return [super forwardingTargetForSelector: aSelector];
        }
    }
    

    3. Normal Fowarding은 상기 두 가지 방법이 모두 실현되지 않으면 세 번째 단계로 넘어간다. 이것은runtime가 우리에게 붕괴를 피할 수 있는 마지막 기회이다. 우선 함수의 매개 변수와 되돌아오는 값 유형을 얻고-methodSignatureForSelector: 되돌아오는 값이면runtimenil이라는 메시지를 보내고 프로그램이 붕괴된다.함수 서명을 되돌려주면runtime는 NSInvocation 대상을 만들고 -doesNotRecognizeSelector: 메시지를 대상 대상에게 보냅니다.
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:"];
        return signature;
    }
    
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
        SEL selector = [anInvocation selector];// anInvocation selector/target/ 
        WWTarget *target = [[WWTarget alloc] init];
        if ([target respondsToSelector:selector]) {
            [anInvocation invokeWithTarget:target];
        }    
    }
    

    위의 세 단계가 모두 이루어지지 않으면 호출-forwardInvocation:되어 프로그램이 붕괴됩니다.

    셋.깊이 복사와 얕은 복사


    딥 카피: 컨텐트 카피, 복사된 객체는 이전 객체와 주소가 다릅니다.얕은 복사: 바늘 복사, 복사된 대상은 이전 대상의 주소와 같다.간단한 예제를 직접 사용하는 것이 좋습니다.
    1. 가변 객체에 대한 작업-doesNotRecognizeSelector:
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSMutableString *mStr = [NSMutableString stringWithString:@"mStr"];
        NSString *copyStr = [mStr copy];
        [mStr appendString:@"123"];
        // mStr:0x60800007f440 - copyStr:0xa0000007274536d4
        NSLog(@"mStr:%p - copyStr:%p",mStr, copyStr);
    }
      :1.    copy  ( )
          2. copy  copyStr NSString , copyStr 
    NSMutableString appendString 。
    

    2. 가변 객체에 대한 작업copy
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSMutableString *mStr = [NSMutableString stringWithString:@"mStr"];
        NSMutableString *mutableCopyStr =  [mStr mutableCopy];
        // str:0x608000260140 - mutableCopyStr:0x608000260440
        NSLog(@"str:%p - mutableCopyStr:%p",mStr, mutableCopyStr); 
    }
      :1.    mutableCopy  ( )
          2. mutableCopy  mutableCopyStr  NSMutableString  
    

    3. 불변 대상에 대한 mutableCopy 조작
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSString *Str = [NSString stringWithFormat:@"Str"];
        NSString *copyStr = [Str copy];
        // str:0x10147e128 - copyStr:0x10147e128
        NSLog(@"str:%p - copyStr:%p",Str, copyStr);
    }
     :    copy  ( )
    

    4. 불변 객체 작업copy
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSString *mStr = [NSString stringWithFormat:@"mStr"];
        NSMutableString *mutableCopyStr = [mStr mutableCopy];
       // str:0xa0000007274536d4 - mutableCopyStr:0x60800026a680
        NSLog(@"str:%p - mutableCopyStr:%p",mStr, mutableCopyStr);
    }
      :1.    mutableCopy   ( )
          2. mStr mutableCopy mutableCopyStr NSMutableString 
    

    상기 서술한 바와 같이 mutableCopy 조작하면 지침 복사(얕은 복사), 나머지는 내용 복사(깊은 복사)

    넷.키보드를 조정할 때 키보드의 "줄 바꾸기" 를 "발송 / 완성" 으로 바꾸는 방법 등

    copy 속성을 설정하면 됩니다.
        UIReturnKeyDefault,
        UIReturnKeyGo,//  
        UIReturnKeyGoogle,// google
        UIReturnKeyJoin,//  
        UIReturnKeyNext,//  
        UIReturnKeyRoute,//  
        UIReturnKeySearch,//  
        UIReturnKeySend, //  
        UIReturnKeyYahoo,//  
        UIReturnKeyDone,//  
        UIReturnKeyEmergencyCall,//  
        UIReturnKeyContinue NS_ENUM_AVAILABLE_IOS(9_0),//  
    

    오.viewDidLayoutSubviews 및 layoutSubviews 호출 순서

    returnKeyType 앞에서 호출viewDidLayoutSubviews 앞에서 호출layoutSubviews 앞에서 호출
    2017-06-14 10:31:35.215 layoutSubviews [7357:98975] -[ViewController viewDidLoad]
    2017-06-14 10:31:35.215 layoutSubviews [7357:98975] -[WWView initWithFrame:]
    2017-06-14 10:31:35.220 layoutSubviews [7357:98975] -[ViewController viewWillLayoutSubviews]
    2017-06-14 10:31:35.220 layoutSubviews [7357:98975] -[ViewController viewDidLayoutSubviews]
    2017-06-14 10:31:35.220 layoutSubviews [7357:98975] -[WWView layoutSubviews]
    2017-06-14 10:31:35.221 layoutSubviews [7357:98975] -[WWView drawRect:]
    

    여섯.분류 동적에 속성을 추가하는 방법

    #import "WWView+Tools.h"
    #import 
    
    static char strKey;
    
    @implementation WWView (Tools)
    
    - (void)setDynamicStr:(NSString *)dynamicStr {
        /**
         id object:  
         const void *key: key 
         id value: value
         objc_AssociationPolicy policy:     NONATOMIC
         */
        objc_setAssociatedObject(self, &strKey, dynamicStr, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)dynamicStr {
        return objc_getAssociatedObject(self, &strKey);
    }
    

    일곱어떻게view를 그림을 만들어서 로컬에 저장합니까


    앨범에 접근하는 것과 관련이 있기 때문에, 우선plist 파일에 layoutSubviews 프로그램을 추가하여 앨범에 접근할 수 있도록 합니다.
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // self.testView: view  
         UIGraphicsBeginImageContextWithOptions(self.testView.bounds.size, 0, [[UIScreen mainScreen] scale]);
            [self.testView.layer renderInContext:UIGraphicsGetCurrentContext()];
            UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            UIImageWriteToSavedPhotosAlbum(viewImage, self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), nil);
        });
    }
    
    - (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
    {
        if (!error) {
            NSLog(@" ");
        }else {
            NSLog(@"  - %@",error);
        }
    }
    

    여덟만약 서버가 우리에게 되돌아온 데이터가 탭을 포함하고 있다면, 우리는 어떻게 불러와야 합니까

    // html_content: html 
    1. UILabel 
    NSMutableAttributedString *attributeStr = [[NSMutableAttributedString alloc] initWithData:[html_content dataUsingEncoding:NSUnicodeStringEncoding] options:@{                                                                                                                                                                                     NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType                                                                                                                                                                                     }documentAttributes:nil error:nil];
    self.contentLabel.attributedText = attributeStr;
    PS: , 
    
    2. UIWebView 
     // 15, rgb(124,181,236), 15, , 
     NSString *html_content = @" html ";
     NSString *htmls = [NSString stringWithFormat:@" 
    " "
    " "
    " "
    " "" "" "window.onload = function(){
    " "var $img = document.getElementsByTagName('img');
    " "for(var p in $img){
    " " $img[p].style.width = '100%%';
    " "$img[p].style.height ='auto'
    " "}
    " "}" "
    %@" "" "",@"rgb(124,181,236)", html_content]; [self.contentWebView loadHTMLString:htmls baseURL:nil];

    아홉앱스토어에 올리는 게 너무 느리면 어떻게 해결해


    Xcode - Open Developer Tool - Application Loader로 해결

    십.Application Loader 패키지를 사용하여 App Store에 커밋하면 오류가 발생할 수 있습니다.

    The filename  .ipa in the package contains an invalid character(s). The valid characters are:A-Z
    ,a-z,0-9,dash,period,underscore,but the name cannot start with a dash,period,or underscore.
    

    해결 방법:Archive 이후의 가방은 중국어 이름을 다시 시도할 수 없습니다. XXX.ipa는 영어 이름으로 바꾸면 돼.

    좋은 웹페이지 즐겨찾기