iOS - FAQ 정리

12476 단어
하나.통지하다
통지에 대해 모두가 낯설지 않을 것이다. 이것은 하나의 예로 사건이 발생할 때 일부 대상을 통지하고 우리가 낮은 정도의 결합 상황에서 통신의 목적을 달성하도록 허용하는 것이다.
알림의 이점: 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];

    }

person에test 메시지를 보낼 때runtime 라이브러리는 대상의isa 지침에 따라 대상이 실제 속하는 클래스를 찾은 다음에 이 클래스의 방법 목록과 부류의 방법 목록에서 해당하는 방법을 찾아 실행합니다. 맨 윗부분의 부류에서 해당하는 방법을 찾지 못하면 프로그램이 실행될 때 unrecognized selector sent to의 오류를 보고하고 붕괴됩니다. 그러나 그 전에objc가 실행될 때 프로그램 충돌을 피할 수 있는 세 번의 기회를 제공합니다.
1. Method resolution objc가 실행될 때 +resolve Instance Method: 또는 +resolve Class Method: 프로그램이 충돌하지 않도록 함수를 제공할 수 있는 기회를 줍니다. 함수가 추가되면 시스템은 메시지를 보내는 과정을 다시 시작합니다. 그렇지 않으면 다음 메시지로 이동합니다.
    + (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 목표 대상이 -forwarding Target For Selector:의 방법을 실현하면runtime는 이 방법을 호출하여 우리에게 이 메시지를 다른 대상에게 전달할 기회를 준다. 이 방법의 반환값이nil과self가 아니라면 전체 메시지가 발송되는 과정은 다시 시작된다. 이때 발송된 대상은 우리가 되돌아오는 이 대상이 되고 그렇지 않으면 다음 단계로 옮겨진다.
    - (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 위의 두 가지 방법이 모두 실현되지 않으면 세 번째 단계로 넘어갑니다. 이것은 런타임이 우리에게 붕괴를 피할 수 있는 마지막 기회입니다. 우선 런타임은 -method Signature For Selector: 함수의 매개 변수와 반환 값 유형을 얻고 반환 값이 nil이면 런타임은 -does Not Recognize Selector:의 메시지를 보내고 프로그램이 붕괴됩니다.함수 서명을 되돌려주면runtime는 NSInvocation 대상을 만들고 - forwardInvocation: 메시지를 대상 대상에게 보냅니다.
    - (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];

        }    

    }

위의 세 단계가 모두 이루어지지 않으면 - does Not Recognize Selector: 를 호출하여 프로그램이 붕괴됩니다.
셋.깊이 복사와 얕은 복사 깊이 복사: 내용 복사, 복사된 대상과 이전 대상의 주소가 다르다.얕은 복사: 바늘 복사, 복사된 대상은 이전 대상의 주소와 같다.간단한 예제를 직접 사용하는 것이 좋습니다.
1. 가변 객체에 대한 copy 작업
    - (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. 가변 객체에 대한 mutableCopy 작업
    - (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. 불변 객체에 대한 copy 작업
    - (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. 불변 객체에 대한 mutableCopy 작업
    - (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 


상기 서술한 바를 종합하면 변할 수 없는 대상에 대한 copy 작업만 지침 복사(얕은 복사), 나머지는 내용 복사(깊은 복사)
넷.키보드를 조정할 때 키보드의 "줄 바꾸기"를 "발송/완성"으로 바꾸는 방법 등
returnKeyType 속성을 설정하면 됩니다.
    UIReturnKeyDefault,

        UIReturnKeyGo,//  

        UIReturnKeyGoogle,// google

        UIReturnKeyJoin,//  

        UIReturnKeyNext,//  

        UIReturnKeyRoute,//  

        UIReturnKeySearch,//  

        UIReturnKeySend, //  

        UIReturnKeyYahoo,//  

        UIReturnKeyDone,//  

        UIReturnKeyEmergencyCall,//  

        UIReturnKeyContinue NS_ENUM_AVAILABLE_IOS(9_0),//  

오.viewDidLayoutSubviews 및 layoutSubviews 호출 순서
viewDidLayoutSubviews 앞에서layoutSubviews 호출drawRect 앞에서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 파일에 NSPhotoLibrary UsageDescription을 추가하여 프로그램이 앨범에 접근할 수 있도록 합니다
    - (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 

     [self.contentWebView loadHTMLString:html_content baseURL:nil];

아홉앱스토어에 올리는 게 너무 느리면 어떻게 해결해
Xcode - Open Developer Tool - Application Loader로 해결

좋은 웹페이지 즐겨찾기