Google同学推荐-编写高质量Objective-C代码的50个有效方法

75 阅读6分钟

1. 命名规范

使用清晰、具有描述性的命名来提高代码可读性。

// Bad
NSString *a = @"Hello";

// Good
NSString *greetingMessage = @"Hello";

2. 使用const修饰符

在不需要修改的情况下,使用const修饰符来定义常量。

// Bad
#define PI 3.14159

// Good
const CGFloat pi = 3.14159;

3. 使用枚举

使用枚举来增强代码的可读性和可维护性。

typedef NS_ENUM(NSInteger, Fruit) {
    FruitApple,
    FruitBanana,
    FruitOrange
};

Fruit selectedFruit = FruitApple;

4. 使用@property和@synthesize

使用@property@synthesize来自动生成访问器方法,并遵循封装原则。

// .h文件
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end

// .m文件
@implementation Person
@synthesize name = _name;
@end

5. 使用instancetype返回对象

使用instancetype关键字来返回实例化的对象,以便于子类化和链式调用。

// Bad
- (id)init {
    return [[Person alloc] initWithName:@"John"];
}

// Good
- (instancetype)init {
    return [[self.class alloc] initWithName:@"John"];
}

6. 使用#pragma mark

使用#pragma mark标识符来将类的实现部分分隔成不同的部分,以提高代码的可读性。

@implementation ViewController

#pragma mark - View Lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

#pragma mark - Private Methods

- (void)doSomething {
    // Implementation
}

@end

7. 使用异常处理

合理使用@try@catch@finally来处理可能出现的异常情况。

@try {
    // Code that may throw an exception
}
@catch (NSException *exception) {
    // Handle the exception
}
@finally {
    // Always executed, whether an exception occurred or not
}

8. 使用分析工具

使用静态代码分析工具(例如clang)来捕获潜在的编码错误和内存泄漏。

9. 使用单例模式

在需要全局访问的类中使用单例模式,确保只有一个实例存在。

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static MyClass *sharedInstance = nil;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
    });
    return sharedInstance;
}

10. 使用dispatch_once创建线程安全的共享实例

+ (instancetype)sharedInstance {
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
    });
    return sharedInstance;
}

11. 使用块(Blocks)捕获变量

void (^simpleBlock)(void) = ^{
    NSLog(@"This is a block");
};

int value = 10;
void (^blockWithVariable)(void) = ^{
    NSLog(@"The value is %d", value);
};

12. 避免循环引用

__weak typeof(self) weakSelf = self;

[self doSomethingWithCompletion:^{
    [weakSelf handleCompletion];
}];

13. 使用NSCache管理缓存

NSCache *cache = [[NSCache alloc] init];
[cache setObject:object forKey:key];
id cachedObject = [cache objectForKey:key];

14. 使用属性修饰符限制访问权限

@property (nonatomic, strong, readonly) NSArray *items;
@property (nonatomic, assign, getter=isHidden) BOOL hidden;

15. 使用类扩展(Class Extension)隐藏私有方法和属性

@interface MyClass ()
- (void)privateMethod;
@property (nonatomic, strong) NSObject *privateProperty;
@end

16. 使用快速枚举

使用快速枚举遍历数组和字典。

NSArray *array = @[ @"Apple", @"Banana", @"Orange" ];
for (NSString *fruit in array) {
    NSLog(@"Fruit: %@", fruit);
}

NSDictionary *dictionary = @{ @"Name": @"John", @"Age": @30 };
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
    NSLog(@"%@: %@", key, value);
}];

17. 使用NSArray和NSDictionary的安全方法

NSArray *array = @[ @"Apple", @"Banana" ];
NSString *fruit = [array objectAtIndex:0];
NSString *unknownFruit = [array objectAtIndex:2]; // 崩溃

NSString *safeFruit = [array objectAtIndex:2 withDefault:@"Unknown Fruit"];

18. 使用NSPredicate进行过滤

NSArray *array = @[ @"Apple", @"Banana", @"Orange" ];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH 'A'"];
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate];

19. 使用dispatch_async执行异步任务

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    // Perform background task
    dispatch_async(dispatch_get_main_queue(), ^{
        // Update UI on the main thread
    });
});

20. 使用NSNotification进行通知传递

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"MyNotification" object:nil];

[[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:nil];

21. 使用KVO观察对象属性的变化

[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"name"]) {
        NSString *newName = change[NSKeyValueChangeNewKey];
        NSLog(@"Name changed to: %@", newName);
    }
}

22. 使用NSFileManager进行文件操作

NSString *path = @"/path/to/file.txt";

NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]) {
    NSError *error = nil;
    [fileManager removeItemAtPath:path error:&error];
    if (error) {
        NSLog(@"Error deleting file: %@", error);
    }
}

23. 使用NSUserDefaults存储用户设置

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"John" forKey:@"UserName"];

24. 使用NSCoding进行对象序列化

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person];
Person *unarchivedPerson = [NSKeyedUnarchiver unarchiveObjectWithData:data];

25. 使用GCD进行多线程编程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Perform background task
    dispatch_async(dispatch_get_main_queue(), ^{
        // Update UI on the main thread
    });
});

26. 使用Core Data进行数据持久化

NSManagedObjectContext *context = [[AppDelegate sharedInstance] managedObjectContext];

NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
[person setValue:@"John" forKey:@"name"];

NSError *error = nil;
if (![context save:&error]) {
    NSLog(@"Error saving context: %@", error);
}

27. 使用Autolayout布局界面

UIView *redView = [[UIView alloc] init];
redView.translatesAutoresizingMaskIntoConstraints = NO;
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

// 添加约束
[redView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20].active = YES;
[redView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20].active = YES;
[redView.widthAnchor constraintEqualToConstant:100].active = YES;
[redView.heightAnchor constraintEqualToConstant:100].active = YES;

28. 使用UICollectionView和UITableView展示集合数据

@interface MyViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>

@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSArray *dataArray;

@end

@implementation MyViewController

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.dataArray.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    
    // Configure the cell
    
    return cell;
}

@end

29. 使用Core Animation创建动画效果

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:self.imageView.layer.position];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
animation.duration = 1.0;
[self.imageView.layer addAnimation:animation forKey:@"positionAnimation"];

30. 使用适用的设计模式

根据不同的情况选择适用的设计模式,例如:单例模式、观察者模式、工厂模式等。

31. 使用弱引用避免循环引用

在block内部使用__weak修饰的引用,避免循环引用。

__weak typeof(self) weakSelf = self;
[self doSomethingWithCompletion:^{
    [weakSelf handleCompletion];
}];

32. 使用断言进行调试

NSAssert(condition, @"Assertion failed: %@", message);
NSAssert2(condition, @"Assertion failed: %@, %@", message1, message2);

33. 使用#pragma unused删除未使用的变量警告

#pragma unused(variableName)

34. 使用运行时机制进行方法交换

Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);

35. 使用NSOperation和NSOperationQueue管理并发任务

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    // Perform the task
}];

[queue addOperation:operation];

36. 使用Core Graphics进行绘图

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
    CGContextFillRect(context, rect);
}

37. 使用UIStackView布局界面

UIStackView *stackView = [[UIStackView alloc] init];
stackView.axis = UILayoutConstraintAxisVertical;
stackView.spacing = 20;
stackView.distribution = UIStackViewDistributionFillEqually;
[stackView addArrangedSubview:view1];
[stackView addArrangedSubview:view2];
[self.view addSubview:stackView];

38. 使用UIActivityIndicatorView显示加载状态

UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = self.view.center;
[activityIndicator startAnimating];
[self.view addSubview:activityIndicator];

39. 使用NSRegularExpression进行正则表达式匹配

NSString *string = @"Hello World";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"Hello" options:0 error:nil];
NSTextCheckingResult *result = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];

40. 使用NSURLSession发送网络请求

NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"https://api.example.com/data"];
[[session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // Handle the response
}] resume];

41. 使用NSXMLParser解析XML数据

@interface MyXMLParser : NSObject <NSXMLParserDelegate>
@end

@implementation MyXMLParser

- (void)parseXMLData:(NSData *)xmlData {
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
    parser.delegate = self;
    [parser parse];
}

- (void)parser:(NSXMLParser *)parser foundElementDeclarationWithName:(NSString *)elementName model:(NSString *)model {
    // Handle the element declaration
}

@end

42. 使用NSURLSessionDownloadTask下载文件

NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"https://example.com/file.zip"];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
    // Handle the downloaded file
}];
[task resume];

43. 使用UIAlertController显示警告和提示框

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    // Handle the OK button tap
}];

[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];

44. 使用CAShapeLayer创建自定义形状

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds cornerRadius:10].CGPath;
shapeLayer.fillColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:shapeLayer];

45. 使用CGAffineTransform进行视图变换

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.transform = CGAffineTransformMakeRotation(M_PI_4);
[self.view addSubview:view];

46. 使用CoreLocation获取设备位置信息

CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager requestWhenInUseAuthorization]; // 请求授权

locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];

47. 使用外观模式简化复杂接口

@interface NotificationManager : NSObject
- (void)registerForRemoteNotifications;
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo;
@end

@implementation NotificationManager
- (void)registerForRemoteNotifications {
    // Register for remote notifications
}
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo {
    // Handle the received notification
}
@end

48. 使用NSKeyedArchiver进行对象序列化

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person];
Person *unarchivedPerson = [NSKeyedUnarchiver unarchiveObjectWithData:data];

49. 使用UITapGestureRecognizer添加手势识别

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self.view addGestureRecognizer:tapGesture];

- (void)handleTap:(UITapGestureRecognizer *)gesture {
    CGPoint location = [gesture locationInView:self.view];
    NSLog(@"Tapped at: %@", NSStringFromCGPoint(location));
}

50. 使用NSUserDefaults存储用户设置

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"John" forKey:@"UserName"];