Objective-C 인코딩 사양 선택

11421 단어
코드는 컴파일할 수 있을 뿐만 아니라, 동시에 '유효' 해야 한다.좋은 코드는 간단명료함, 자기 해석, 우수한 조직, 좋은 문서, 좋은 명칭, 우수한 디자인과 오랜 시련을 겪을 수 있는 특징이 있다.《선과 Objective-C 프로그래밍 예술》
일상적인 개인과 팀 인코딩 습관에 따라 몇 가지 Objective-C 코드 규범을 정리하고 이 글을 정리하여 지속적으로 업데이트합니다.여러 가지 규범과 사고방식은 이라는 책을 참고하여 매우 추천합니다.

명명 규칙


낙타봉명

  • 속성, 변수, 방법(iOS에서의 방법, 규범적인 명칭은 메시지)이어야 한다. 모두 소문자로 시작하는 낙타봉을 사용한다.
  • 글로벌 변수 이름은 소문자 g로 시작합니다.
  • static CSDataManager *gDataManager = nil; // good
    static CSDataManager *dataManager = nil; // avoid
    

    접두사

  • 클래스 이름, 프로토콜 이름, 열거 유형, 매크로는 프로젝트 접두사로 시작하고 프로젝트 접두사는 2-3개의 대문자로 시작한다. 예를 들어 본 문서는 CS(CodeStyle 줄임말)를 프로젝트 접두사로 한다.
  • @interface OCBaseViewController : UIViewController
    @end
    
  • ""처음에 인스턴스 변수를 사용하여 인스턴스 변수를 직접 대체합니다.
  • @interface ViewController () {
        BOOL _hasViewed; // avoid
    }
    @property (nonatomic, assign) BOOL isToday; // good
    @end
    
  • 사유방법도 ""처음에는 C++ 표준이고 ""접두사는 애플이 보유하고 있으니 애플을 다시 싣는 개인적인 방법에 위험을 무릅쓰지 마라.#pragma를 사용하여 코드 블록에서 개인 방법을 구분할 수 있습니다.
  • - (void)_privateMethod { // avoid
    }
    
    #pragma mark - Private Method
    - (void)privateMethod { // good
    }
    
  • 집행적인 방법은 동사로 시작하고, 되돌아오는 방법은 내용으로 시작하지만, 이전에는 get
  • 을 추가하지 마십시오.
    - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; //    ,good
    + (id)arrayWithArray:(NSArray *)array; //    ,good
    + (id)getArrayWithArray:(NSArray *)array; //    ,avoid
    

    코드 형식


    스페이스 바

  • 포인터 "*"번호의 위치는 변수 유형이 아닌 변수 이름 앞에 있고 변수 이름 뒤에 공백이 없고 유형 사이에 공백이 있습니다.
  • @property (nonatomic, strong) NSString* name;       // avoid
    @property (nonatomic, strong) NSString *password;   // good
    
  • "{"와 "("앞에는 모두 빈칸이 필요하고, "}"뒤에 내용, 예를 들어else와 같은 내용이 뒤따르려면 빈칸이 필요하지만, "("와 "["오른쪽, ")"과 "]"왼쪽에는 빈칸이 있을 수 없습니다.관련 위치:if-else,while,방법 성명 및 실현,@interface 등.
  • -(void)viewDidLoad{ // avoid
        [super viewDidLoad];
        if([self isOk]){ // avoid
            // ...
        }else{ // avoid
            // ...
        }
    }
    
    - (void)viewDidLoad { // good
        [super viewDidLoad];
        if ([self isOk]) { // good
            // ...
        } else { // good
            // ...
        }
    }
    
  • ++와 --을 제외한 연산자는 앞뒤에 공백이 필요합니다.
  •     if ( i>10 ) { // avoid
            i ++; // avoid
        } else {
            i+=2; // avoid
        }
        
        // good
        if (i > 10) {
            i++;
        } else {
            i += 2;
        }
    
  • ","왼쪽에는 공백이 없고 오른쪽에는 한 칸
  • 이 비어 있음
    @property (nonatomic,readonly ,strong) NSString* name; // avoid
    NSArray *array = @[@"A" , @"B" ,@"C"]; // avoid
    
    @property (nonatomic, readonly, strong) NSString* name; // good
    NSArray *array = @[@"A", @"B", @"C"]; // good
    
    

    괄호

  • if,else 뒤에는 코드가 한 줄만 있어도 "{}"을 따라가야 합니다.이후에 논리를 추가할 때 증가 {}를 무시하는 것을 방지하고 논리 코드는if,else 이외로 이동하며 읽기에 더욱 편리합니다.
  •     if (i > 10) // avoid
            i++;
        else
            i--;
        
        
        if (i > 10) { // good
            i++;
        } else {
            i--;
        }
    
  • if-else에서else는 다른 줄을 만들지 않고if의 반괄호와 같은 줄에 있습니다. 위 코드와 같이else의 앞뒤에 빈칸이 있음을 주의하십시오.
  • 괄호는 통일적으로 줄을 바꾸지 않는 스타일을 채택한다.관련 위치: @interface, 방법 실현,if-else,switch-case 등.장점: 코드의 불필요한 줄 수를 줄이고 코드가 더욱 치밀하며 구조가 뚜렷하다.
  • // avoid
    - (void)test
    {
        if ([self isOK])
        {
            // ...
        }
        else
        {
            // ...
        }
    }
    
    
    // good
    - (void)test {
        if ([self isOK]) {
            // ...
        } else {
            // ...
        }
    }
    
  • switch-case에서case 뒤의 코드가 한 줄 남으면 {}소포가 필요합니다. 모든case와default 뒤의 코드 블록은 {}소포를 사용하도록 권장합니다.

  • 등록 정보

  • 실례 변수를 직접 @property로 대체하고 @synthesize와 @dynamic
  • 를 사용하지 않습니다.
  • @property 괄호 안에 있는 설명적인 수식자는 원자성, 읽기, 메모리 관리 등 다음과 같은 순서로 작성됩니다.세 가지 묘사 문자가 자주 수정되어야 하기 때문에 속성과 속성 간의 차이가 비교적 큰 것은 메모리 관리이고 그 다음은 읽기와 쓰기와 원자성이다. 오른쪽에서 왼쪽으로 수정하기 편리하고 코드의 앞부분을 비교적 아름답게 맞출 수 있다.
  • // avoid
    @property (copy, nonatomic, readonly) NSString *name;
    @property (nonatomic, assign, readonly) NSInteger age;
    @property (readwrite, strong, nonatomic) CSCard *card;
    
    // good
    @property (nonatomic, readonly, copy) NSString *name;
    @property (nonatomic, readonly, assign) NSInteger age;
    @property (nonatomic, readwrite, strong) CSCard *card;
    
  • 소프트 유형은 아니지만 소프트 유형(Mutable) 객체에 값을 부여할 수 있는 속성, 예를 들어 NSString, NSArray, NSDictionary, NSURLRequest 등 메모리 관리 속성 유형은 copy여야 합니다.선언된 불변의 속성을 방지하기 위해 실제 값을 부여하는 것은 가변 대상이고 대상의 내용이 알지 못하는 상황에서 외부에서 수정된다.
  •     @property (nonatomic, copy) NSString *name; // good
    
        NSMutableString * name = [[NSMutableString alloc] initWithString:@"User1"];
        CSUserModel *user = [CSUserModel new];
        user.name = name;
        [name appendString:@"0"];
        NSLog(@"%@", user.name); // output:User1
        
            
        @property (nonatomic, strong) NSString *name; // avoid
    
        NSMutableString * name = [[NSMutableString alloc] initWithString:@"User1"];
        CSUserModel *user = [CSUserModel new];
        user.name = name;
        [name appendString:@"0"];
        NSLog(@"%@", user.name); // output:User10, Something Wrong!
    
  • 클래스의 헤더 파일에 가변 대상이 노출되는 것을 피하고readonly 메모리 관리와 가변 대상을 사용하여 외부 호출자가 내부 표시를 바꾸고 봉인성을 파괴하는 것을 방지하는 것을 권장합니다.
  • init와 dealloc에서 점문법 접근 속성을 사용하지 않기 때문에 이 두 곳에 직접 접근해야 한다""시작 인스턴스 변수입니다.init에서 setter나 Getter에 접근하기 때문에 하위 클래스를 다시 쓴 방법에 접근할 수 있으며, 방법 내에서 초기화되지 않았거나 불안정한 속성을 사용하거나 다른 방법을 방문해서 기대 이외의 상황이 발생할 수 있습니다.주: init가 되돌아온 후에만 대상이 초기화되어 사용할 수 있음을 표시합니다.dealloc 방법에서 대상이 방출되기 전의 불안정한 상태입니다.setter,getter에 접근하면 문제가 발생할 수 있습니다.
  • 속성은 점 문법 접근을 사용하여 방법 호출과 구분하는 것을 권장합니다.그러나 setter, Getter의 속성을 다시 쓴 경우 코드 읽는 사람이 방문한 이 setter, Getter가 다시 쓴 것으로 부작용이 있을 수 있음을 알려주는 방법으로 접근할 수 있다.

  • 기타 문법

  • if문장을 비교할 때 괄호 안에nil, NO 또는 YES
  • 를 사용하지 않는다
        if (obj == nil && finish == YES && result == NO){ // avoid
            
        }
        
        if(!obj && finish && !result){ // good
            
        }
    
  • @throw, @try, @catch, @finally의 사용을 최대한 줄이면 성능에 영향을 줄 수 있음
  • 코드에 고정된 문자열과 숫자를 상수로 대체하여 이해, 찾기, 교체를 편리하게 한다.상수는 static 성명을 정적 상수로 사용하십시오. 특수한 작용이 있어야만 #define
  • 을 사용할 수 있습니다

    줄을 바꾸다

  • 두 줄 이상의 빈 줄을 사용하지 않도록 #import, @interface, @implementation, 방법과 방법 사이에 두 줄의 빈 줄을 간격으로 하는 것을 권장합니다.
  • 방법에서는 한 줄의 빈 줄을 사용하여 서로 다른 기능의 코드 블록을 분리할 수 있지만, 통상적으로 서로 다른 기능의 코드 블록은 새로운 방법을 추출하는 것을 고려해야 한다.
  • 3개 이상의 매개 변수를 포함하는 방법으로 서명하고 각 매개 변수에 대해 줄을 바꾸는 것을 권장하며 매개 변수는 사칭에 따라 코드를 더욱 읽을 수 있고 수정하기 편리하도록 한다.
  • // avoid
    + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion {
        // ...
    }
    
    // good
    + (void)animateWithDuration:(NSTimeInterval)duration
                     animations:(void (^)(void))animations
                     completion:(void (^)(BOOL finished))completion {
        // ...
    }
    

    메모

  • 단일행 주석, "//"다음에 한 칸을 비우고 구체적인 주석 내용을 쓰고, "//"주석이 코드와 같은 줄에 있으면 코드의 마지막 문자를 한 칸 비우고 주석
  • 을 쓴다
    // avoid
    - (void)test {
        //Just For Debug
        BOOL isTest = YES;//Main Logic
        //...
    }
    
    // good
    - (void)test {
        // Just For Debug
        BOOL isTest = YES; // Main Logic
        // ...
    }
    
  • 메소드 서명에 여러 줄 주석을 사용하고 Xocde 스타일의 "Editor-structure-Add Document"에 따라 추가합니다.Description 부분에서 첫 번째 줄은 가장 간단한 문장으로 방법을 설명하고 상세한 설명이 필요하면 한 줄을 비운 후에 상세한 설명을 한다.
  • /**
       xxx  ,    。
     
     xxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxx(      )
    
     @param error NSError,-1:xxx;-2:xxxxx
     */
    - (void)methodWithError:(NSError **)error {
        // ...
    }
    

    코드 조직


    #pragma

  • 한 파일의 코드에 대해 "#pragmamark - CodeBlockName"을 사용하여 세그먼트를 나누어 코드 유지보수와 읽기가 쉽습니다.흔히 볼 수 있는 구분 근거와 형식은 다음과 같다.
  • - (void)dealloc { /* ... */ }
    - (instancetype)init { /* ... */ }
    
    #pragma mark - View Lifecycle
    - (void)viewDidLoad { /* ... */ }
    - (void)didReceiveMemoryWarning { /* ... */ }
    
    #pragma mark - Setter Getter
    - (void)setCustomProperty:(id)value { /* ... */ }
    - (id)customProperty { /* ... */ }
    
    #pragma mark - IBActions
    - (IBAction)onOkButtonClick:(id)sender { /* ... */ }
    
    #pragma mark - Public
    - (void)publicMethod { /* ... */ }
    
    #pragma mark - Private
    - (void)privateMethod { /* ... */ }
    
    #pragma mark - UITableViewDelegate
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { /* ... */ }
    
    #pragma mark - Superclass
    - (void)superClassMethod { /* ... */ }
    
    #pragma mark - NSObject
    - (NSString *)description { /* ... */ }
    
  • @interface가 실현된 프로토콜을 설명할 때 하나의 프로토콜이 한 줄을 차지하고 @interface가 있는 줄은 프로토콜 이름을 쓰지 않습니다.읽기와 수정에 편리하도록 하다.
  • // avoid
    @interface CodeStyleViewController () 
    @end
    
    // good
    @interface CSViewController () <
    UITableViewDelegate,
    UITableViewDataSource,
    UIActionSheetDelegate
    >
    @end
    
  • dealloc 방법의 실현은 파일의 맨 앞에 두어야 합니다. 일반적으로 @implementation 다음에 init나viewDidLoad 앞에 놓아서 검사하기 쉽도록 합니다.
  • 주 논리 코드의 집행이 여러 조건을 충족시켜야 할 때if문장의 끼워넣기를 피한다. 이때return문장을 사용하면if문장의 끼워넣기를 줄이고 순환의 복잡도를 낮추며 조건과 주 논리의 명확한 지역을 분리할 수 있다.
  • // avoid
    - (void)method {
        if ([self conditionA]) {
            // some code..
            if ([self conditionB]) {
                // main logic...
            }
        }
    }
    
    // good
    - (void)methodB {
        if (![self conditionA]) {
            return;
        }
        
        if (![self conditionB]) {
            return;
        }
        
        // some codeA..
        // main logic...
    }
    

    인터페이스 사양

  • 공유 API를 간단명료하게 유지: 공개하고 싶지 않은 방법과 속성에 대해서만m 파일에서 실현을 성명합니다.h 파일에서 공개해야 하는 방법/속성만 설명합니다.
  • 위탁 모드에서 성명한 @protocol 이름은 위탁 클래스 이름(예를 들어 UItableView)으로 시작하고 그 다음에 "Delegate"또는 "Protocol"을 추가해야 한다.
  • @protocol에서 설명하는 방법은 의뢰 클래스 이름으로 프로젝트 접두사를 제거한 단어로 시작하고 첫 번째 파라미터는 의뢰 대상이 되어야 합니다. 그렇지 않으면 의뢰 클래스가 여러 개의 의뢰를 대리할 때 이 의뢰 방법이 어느 의뢰 대상에서 발기되었는지 구분할 수 없습니다.
  • @class CSShareViewController;
    @protocol CSShareDelegate  // avoid
    
    - (void)shareFinished:(BOOL)isSuccess; // avoid
    
    @end
    
    
    
    @class CSShareViewController;
    @protocol CSShareViewControllerDelegate  // good
    
    - (void)shareViewController:(CSShareViewController *)shareViewController // good
                  shareFinished:(BOOL)isSuccess;
    
    @end
    
  • 실패할 수 있습니다. error를 던지는 방법이 필요합니다. BOOL 반환값은 방법의 주요 기능 논리적 성공 여부를 나타냅니다.이 인터페이스를 사용하면 먼저 검사 방법으로 값을 되돌려주고 error에 따라 상응하는 처리를 합니다.애플 API는 성공적인 상황에서도 error에 스팸 데이터를 쓰는 경우가 있다.
  • // avoid
    - (void)methodWithError:(NSError **)error {
        // ...
    }
    
    - (void)test1 {
        NSError *error = nil;
        if ([self methodWithError:&error]) { // avoid
            // Main Logic
        } else {
            // Handle Error
        }
    }
    
    // good
    - (BOOL)methodWithError:(NSError **)error {
        // ...
    }
    - (void)test {
        NSError *error = nil;
        if ([self methodWithError:&error]) { // good
            // Main Logic
        } else {
            // Handle Error
        }
    }
    
    

    참조 기사: * 선 및 Objective-C 프로그래밍 아트
    내 블로그 원본: Objective-C 인코딩 사양 선택

    좋은 웹페이지 즐겨찾기