OC CodeBlock

创建时间:2021-04-22

本文旨在将编码过程变为模块化、对象化的过程
 

一、基本控件的初始化

UILabel

- (UILabel *)remindLabel {
    if (!_remindLabel) {
        _remindLabel = [[UILabel alloc] init];
        _remindLabel.frame = CGRectMake(0, kStatusBarHeight+90, kScreenWidth, 20);
        _remindLabel.textColor = [UIColor colorWithHexString:@"#60b4e6"];
        _remindLabel.font = kRegularFont(14);
        _remindLabel.textAlignment = NSTextAlignmentCenter;
        _remindLabel.backgroundColor = [UIColor clearColor];
        [self.view addSubview:_remindLabel];
    }
    return _remindLabel;
}

UIImageView

- (UIImageView *)imgView {
    if (!_imgView) {
        _imgView = [[UIImageView alloc] init];
        _imgView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
        _imgView.backgroundColor = [UIColor clearColor];
        _imgView.contentMode = UIViewContentModeScaleAspectFill;
        [self addSubview:_imgView];
    }
    return _imgView;
}

UIButton

- (UIButton *)publishBtn {
    if (!_publishBtn) {
        _publishBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        _publishBtn.frame = CGRectMake(kScreenWidth-67, kStatusBarHeight+3, 62, 32);
        [_publishBtn setTitle:@"发布" forState:UIControlStateNormal];
        _publishBtn.titleLabel.font = kMediumFont(16);
        [_publishBtn setTitleColor:[UIColor colorWithHexString:@"#0A1F44"] forState:UIControlStateNormal];
        [_publishBtn setBackgroundColor:[UIColor clearColor]];
        [_publishBtn addTarget:self action:@selector(requestOfPublishDynamic) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_publishBtn];
    }
    return _publishBtn;
}

UITextView

- (UITextView *)textView {
    if (!_textView) {
        _textView = [[UITextView alloc] init];
        _textView.font = kRegularFont(14);
        _textView.showsHorizontalScrollIndicator = false;
        _textView.backgroundColor = KRGB(0xF7F7F7);
        _textView.showsVerticalScrollIndicator = false;
        _textView.returnKeyType = UIReturnKeySend;
        _textView.delegate = self;
        _textView.text = @"请输入消息...";
        _textView.textColor = KRGB(0xC1C0C9);
        [_textContainerView addSubview:_textView];
    }
    return _textView;
}

UIScrollView

- (UIScrollView *)scrollView {
    if (!_scrollView) {
        _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 40, kScreenWidth, WhiteBgViewHeight-40)];
        _scrollView.delegate = self;
        _scrollView.backgroundColor = [UIColor whiteColor];
        _scrollView.pagingEnabled = YES;
        _scrollView.showsVerticalScrollIndicator = NO;
        _scrollView.showsHorizontalScrollIndicator = NO;
        [self addSubview:_scrollView];
        _scrollView.contentSize = CGSizeMake(2*kScreenWidth, 0);
    }
    return _scrollView;
}

UITableView

//UITableView懒加载
- (UITableView *)tableView {
    if (!_tableView) {
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, kTopHeight, KScreenWidth, KScreenHeight-kTopHeight) style:UITableViewStyleGrouped];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.backgroundColor = kSystemBgColor;
        [_tableView setSeparatorColor:kSystemBgColor];
        [_tableView registerClass:[LWYMyCollectionCell class] forCellReuseIdentifier:@"cellID"];
        _tableView.separatorStyle = UITableViewCellEditingStyleNone;     //让tableview不显示分割线
        [self.view addSubview:_tableView];

        kWeakSelf(self);        
        // 下拉刷新,上拉加载更多
        _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
            [weakself requestOfMyCollectionData:YES];
        }];
        _tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
            // 上拉加载更多
            [weakself requestOfMyCollectionData:NO];
        }];
        
        // 为tableView添加长按手势
        UILongPressGestureRecognizer *longPressGr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
        longPressGr.minimumPressDuration = 0.5f;
        longPressGr.numberOfTouchesRequired = 1;
        [_tableView addGestureRecognizer:longPressGr];
        _tableView.userInteractionEnabled = YES;
    }
    return _tableView;
}

//长按Cell的动作
- (void)longPressAction:(UILongPressGestureRecognizer *)longRecognizer {
    if (longRecognizer.state == UIGestureRecognizerStateBegan) {
        CGPoint point = [longRecognizer locationInView:_tableView];
        NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:point]; // 可以获取我们在哪个cell上长按
        if (indexPath != nil) {
            
        }
    }
}

UICollectionView

- (UICollectionView *)collectionview {
    if (!_collectionview) {
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
        _collectionview = [[UICollectionView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.searchbarView.frame) + 10, kScreenWidth, kScreenHeight*2.0/3.0 - 100) collectionViewLayout:flowLayout];
        _collectionview.delegate = self;
        _collectionview.dataSource = self;
        _collectionview.backgroundColor = [UIColor clearColor];
        _collectionview.showsVerticalScrollIndicator = NO;
        [_collectionview registerClass:[LWYPersonalTagCell class] forCellWithReuseIdentifier:@"cellID"];
        [self addSubview:_collectionview];
    }
    return _collectionview;
}


二、TableView相关

UITableView刷新单独的section或row

// 刷新section
NSIndexSet * indexSet = [[NSIndexSet alloc]initWithIndex:1];
[tableview reloadSections: indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
// 刷新row
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:2 inSection:1];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];

UITableView滚动到最后一行有数据的cell

类似于微信进入聊天详情后,最新的一条消息在最底部,但是如果消息条数过少,又不会cell硬塞到最底部

/// 滑动到最底部
- (void)scrollToBottom {
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01/*延迟执行时间*/ * NSEC_PER_SEC));
    dispatch_after(delayTime, dispatch_get_main_queue(), ^{
        if (self.dataSource.count > 0) {
            if ([self.tableView numberOfRowsInSection:0] > 0) {
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0]-1) inSection:0];
                [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
            }
        }
    });
}

判断UIScrollView/UITableView是向上还是向下滑动

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGPoint point = [scrollView.panGestureRecognizer translationInView:scrollView];
    CGFloat offsetY = point.y;
    if (offsetY < 0) {
        // 下滑
    } else {
        // 上滑
    }
}

获取TableView或CollectionView可视范围(自身frame)的Cell

self.tableView.visibleCells
self.collectionView.visibleCells

去除tableView底部多余行和分割线

tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

tableView.tableFooterView = nil;

隐藏所有分割线

tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

设置分割线的颜色

tableView.separatorColor = [UIColor redColor];


三、协议和代理/委托

Delegate声明步骤

A类

Aclass.h

//1.声明协议
@protocol AclassDelegate 
@required //成为A类的代理/委托的类中必须实现的方法
- (void)mustDoSomething;
@optional //成为A类的代理/委托的类中可选择是否实现的方法
- (void)optionalDoSomething;
@end

//2.声明属性
@interface Aclass : NSObject
@property (nonatomic, weak) id delegate;
@end

Aclass.m

//6.委托方通知代理人执行相应方法
if ([self.delegate respondsToSelector:@selector(mustDoSomething)]) 
   [self.delegate mustDoSomething];
}

B类

Bclass.m
//3.代理人签订协议
@interface Bclass () 
@property (nonatomic, strong) Aclass *a;
@end

//4.委托方指定代理人
a.delegate = self;

//5.代理人实现协议方法
- (void *)mustDoSomething {}


四、NSURLSession

1. NSURLSessionDataTask发送get请求

// 1.创建request相关数据
NSString *str = @"http:/localhost:80/api/hello.json";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

// 2.使用NSURLSession创建task任务
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (data) {
        NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        if (result) {
            dispatch_async(dispatch_get_main_queue(), ^{

            });
        }
    }
}];

// 3.执行task任务
[task resume];

2. NSURLSessionDataTask发送post请求

// 1.创建request相关数据(post请求需要设置请求头和请求体,使用NSMutableURLRequest)
NSString *str = @"http:/localhost:80/api/hello.json";
NSURL *url = [NSURL URLWithString:str];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

// 2.使用NSURLSession创建task任务
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (data) {
        NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        if (result) {
            dispatch_async(dispatch_get_main_queue(), ^{

            });
        }
    }
}];

// 3.执行task任务
[task resume];

3. NSURLSessionDataTask设置代理发送请求

- (void)requestWithDelegate {
    // 1.创建request相关数据
    NSString *str = @"http:/localhost:80/api/hello.json";
    NSURL *url = [NSURL URLWithString:str];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    
    // 2.配置NSURLSession并设置其代理(queue是设置队列,若设置为nil,则默认在子线程中执行)
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    
    // 3.使用NSURLSession创建task任务
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    
    // 4.执行task任务
    [dataTask resume];
}

#pragma mark - NSURLSessionDelegate

- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
    //子线程中执行
    NSLog(@"接收到服务器响应的时候调用 -- %@", [NSThread currentThread]);
    
    self.resultData = [NSMutableData data];
    //默认情况下不接收数据
    //必须告诉系统是否接收服务器返回的数据
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveData:(nonnull NSData *)data {
    NSLog(@"接受到服务器返回数据的时候调用,可能被调用多次");
    //拼接服务器返回的数据
    [self.resultData appendData:data];
}

- (void)URLSession:(NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error {
    NSLog(@"请求完成或者是失败的时候调用");
    //解析服务器返回数据
    NSLog(@"%@", [[NSString alloc] initWithData:self.resultData encoding:NSUTF8StringEncoding]);
}

#pragma mark - 设置代理后解决强引用问题

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    [self.session invalidateAndCancel]; //方法直接取消请求然后释放代理对象
    [self.session finishTasksAndInvalidate]; //方法等请求完成之后释放代理对象
}

4. NSURLSessionDataTask 简单下载

// 1.创建request下载地址相关数据
NSString *str = @"http:/localhost:80/resource/IMG_1604.JPG";
NSURL *url = [NSURL URLWithString:str];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 2.使用 NSURLSession 对象创建一个 NSURLSessionDataTask 请求
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (data) {
        UIImage *img = [UIImage imageWithData:data];
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
            imgView.image = img;
            [self.view addSubview:imgView];
        });
    }
}];

// 3.执行task任务
[task resume];

5. NSURLSessionDownloadTask 简单下载

// 1.创建request下载地址相关数据
NSString *str = @"http:/localhost:80/resource/IMG_1604.JPG";
NSURL *url = [NSURL URLWithString:str];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 2.使用 NSURLSession 对象创建一个 NSURLSessionDownloadTask 请求
NSURLSessionDownloadTask *downloadTask = [[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    //默认存储到临时文件夹 tmp 中
    NSLog(@"%@", location);//目标位置

    //需要剪切文件到 cache
    NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
                                stringByAppendingPathComponent:response.suggestedFilename];
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
}];

// 3.执行task任务
[downloadTask resume];

五、block代码块

1.block的声明

typedef void (^CompleteBlock)(void);

2.block作为属性(修饰符要使用copy)

//使用定义过的代码块
@property (nonatomic, copy) CompleteBlock block;

//直接在属性中定义
@property (nonatomic, copy) void (^completeBlock)(void);

3.block作为方法的参数

//使用定义过的代码块
- (void)doSomethingMethod:(CompleteBlock)block {
    //做完了所需的操作后,执行block回调
    block();
}

//直接在方法中定义
+ (void)doSomethingMethod:(void (^)(BOOL result, NSString *errorStr))block {
    //做完了所需的操作后,执行block回调
    if (1) {
        block(YES, @"");
    } else {
        block(NO, @"这里是错误的原因");
    }
}

4.block实现两个类之间的方法回调(同协议代理Delegate)

上面的delegate协议总共有6步,如果用block的话可以缩减为3步:


bolck实现回调流程

A类

//1.定义一个名为completeBlock的代码块属性
@property (nonatomic, copy) void (^completeBlock)(void);

//2.在需要的时候执行block
if (self. completeBlock) {
    self. completeBlock();
}

B类

//3.初始化A类的对象a时
- (Aclass *)a {
    if (!_a) {
        _a = [[Aclass alloc] init];
        [_a setCompleteBlock:^{
            //次数为B执行的方法
        }];
    }
    return _a;
}

3.利用block来实现一个异步方法执行完成的回调

/// 从服务器异步下载文件,并保存到本地生成地址
/// @param serverUrl 文件在服务器的url
/// @param completedBlock 完成回调
- (void)downloadFileFromUrl:(NSString *)serverUrl completed:(void (^)(BOOL successed, NSString *filePath))completedBlock {
    //开启异步子线程下载文件
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSString *filePath = @"此处为设置的文件地址";
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:serverUrl]];
        if ([data writeToFile:filePath atomically:YES]) {
            completedBlock(YES, filePath);
        } else {
            completedBlock(NO, @"");
        }
    });
}


判断文件夹下是否存在指定文件(根据文件路径和文件名)

//1.获取文件的路径
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", docPath,此处为目标文件的文件名];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
   //文件存在
} else {
   //文件不存在
}

在使用 fileExistsAtPath 判断的时候,如果不管本地是否存在的情况下一直返回NO,有可能是使用了绝对路径,如NSHomeDirectory(),此时应使用NSSearchPathForDirectoriesInDomains()来获取相对路径,而此方法只能获取Documents和Cache文件夹,不能获取Tmp文件夹。

UIImage加载本地图片

 [UIImage imageWithContentsOfFile:imgPath];

使用NSData对象将文件写入本地指定路径

if ([fileData writeToFile:filePath atomically:YES]) {
    //写入成功        
} else {
    //写入失败
}

加载本地的gif图片

#import "UIImage+GIF.h"

NSData *data = [NSData dataWithContentsOfFile:imgPath];
UIImage *gifImage = [UIImage sd_imageWithGIFData:data];

AES加密解密

.h
/// AES加密
/// @param key 加密的密钥
- (NSData *)aes256_encrypt:(NSString *)key;
/// AES解密
/// @param key 解密的密钥
- (NSData *)aes256_decrypt:(NSString *)key;

.m
// AES加密
- (NSData *)aes256_encrypt:(NSString *)key {
    char keyPtr[kCCKeySizeAES256 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [self bytes], dataLength, buffer, bufferSize, &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}
// AES解密
- (NSData *)aes256_decrypt:(NSString *)key {
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }
    free(buffer);
    return nil;
}

从服务器上获取AES加密过的文件,并将其解密后保存到本地(异步)

在AES的解密过程中,如果需要解密多个文件的话,需要使用异步的方式,以免阻塞主线程。此方法模仿SD_WebImage的实现,在方法的回调中返回了保存过后的文件地址,供如加载图片等各个方法的使用:

/// 从服务器下载加密后的文件,并解密后保存到本地生成地址(异步)
/// @param serverUrl 文件在服务器的url
/// @param key 解密的key
/// @param completedBlock 完成回调
+ (void)downloadFileFromUrl:(NSString *)serverUrl aes256decrypt:(NSString *)key completed:(void (^)(BOOL successed, NSString *filenamePath))completedBlock {
    //1.提取文件名
    NSString *nameStr = [serverUrl componentsSeparatedByString:@"/"].lastObject;
    
    //2.获取沙盒Document地址
    NSString *documentsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    
    //3.在沙盒地址下新建文件夹,并生成文件地址(带文件名)
    NSString *folderPath = [documentsDir stringByAppendingPathComponent:@"AESCryptFiles"];
    BOOL isDir = NO;
    BOOL existed = [[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) ) {
        [[NSFileManager defaultManager] createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    NSString *filePath = [NSString stringWithFormat:@"%@/%@",folderPath, nameStr];
    
    //4.判断文件是否已存在,如果已存在那么直接返回地址,如果不存在,那么下载后解压保存
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        //文件已存在,直接返回
        completedBlock(YES, filePath);
        return;
    }
    //文件不存在,解密后返回(异步)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:serverUrl]];
        NSData *fileData = [data aes256_decrypt:key];
        if ([fileData writeToFile:filePath atomically:YES]) {
            completedBlock(YES, filePath);
        } else {
            completedBlock(NO, @"");
        }
    });
}

利用MJExtension讲json字典转化为模型时,对id这类关键字的处理

+ (NSDictionary *)mj_replacedKeyFromPropertyName {
    return @{@"tagId": @"id"};
}

AppDelegate中设置指定控制器为根控制器

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
GQTimerViewController *vc = [[GQTimerViewController alloc] initWithNibName:@"GQTimerViewController" bundle:nil];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];

判断文件夹下是否存在指定文件

NSString *fileName = @"04.jpg";
NSArray *DocumentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filepath = [[NSString alloc] initWithString:[NSString stringWithFormat:@"%@/%@",DocumentPath[0],fileName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filepath]) {
    NSLog(@"file is exists");
} else{
    NSLog(@"file is not exists");
};

加载本地Gif图片

NSString *path = [[NSBundle mainBundle] pathForResource:@"ai_animation" ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage sd_imageWithGIFData:data];

boundingRectWithSize计算文字高度不准问题

//使用ceilf函数
CGSize size = [extraModel.txtContent boundingRectWithSize:CGSizeMake(kScreenWidth-140, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17]} context:nil].size;
        extraModel.txtLabelH = ceilf(size.height);

将指定View的显示内容截取成图片

/// 截取指定View的图片
/// @param currentView 需要被截取的View
- (UIImage *)captureScreenForView:(UIView *)currentView {
    UIGraphicsBeginImageContextWithOptions(currentView.frame.size, NO, [UIScreen mainScreen].scale);
    [currentView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}

UIButton实现左边文字,右边图片

[btn setTitleEdgeInsets:UIEdgeInsetsMake(0, -btn.imageView.image.size.width, 0, btn.imageView.image.size.width)];
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, btn.titleLabel.bounds.size.width, 0, -btn.titleLabel.bounds.size.width)];

你可能感兴趣的:(OC CodeBlock)