一.图片缓存
ActivityModel.m
如果数据加载完毕就将图片放到缓存中.
#pragma mark -- imageDownLoader 代理方法
//  成功返回data
- (void)imageDownSucceedWithData:(NSData *)data
{
    //  给model里的图片 赋值
    self.getUrlImage = [UIImage imageWithData:data];
    //  标识加载完毕
    _isDownloading = NO;
    //  图片缓存
    FileManager *manager = [FileManager shareManager];
    [manager saveImageData:data imageURl:self.image];
}
在给model对象赋值的时候, 用的是KVC 方法,其实内部调用的是setValue forKey 的方法.所以就改写里面的方法,如果缓存区里有图片就不从网上download,直接从缓存路径下面去读取图片.
读缓存的思路
        1. 图片显示在cell 上,需要看显示图片的方法
        2. 当model 中的getUrlImage为空的时候是去请求图片的,
        3. 现在需要加载缓存.
        4. 不请求 就是model 中的getUrlImage 不为空
        5. 如果给 getUrlImage 赋值 缓存中的图片 就 达到目的了
        6. 新问题: 如何给 getUrlImage 赋值 缓存中的图片?
        7. 利用图片的 网址 可以找到对应的缓存图片
        8. 如何在一开始赋值的时候 就把缓存中的图片赋值model
        9. 一开始的赋值 在setValue ForKey 方法中
//setValueforkeywithDictionary:Dic  实际上多次调用下面的方法
- (void)setValue:(id)value forKey:(NSString *)key
{
    [super setValue:value forKey:key];
  if([key isEqualToString:@"image"]) {
        // 这时 value 就是图片的网址
        self.image = value;
        // 给self.getUrlImage 加载缓存
        self.imagePath = [[FileManager shareManager] imagesPathWithImageUrl:self.image];
        self.getUrlImage = [UIImage imageWithContentsOfFile:self.imagePath];
    }
}
FileManager.h
#import <Foundation/Foundation.h>
@interface FileManager : NSObject
+ (FileManager *)shareManager;
- (void)saveImageData:(NSData *)imageData imageURl:(NSString *)imageUrl;
// 传url 返回一个URL 完整路径
- (NSString *)imagesPathWithImageUrl:(NSString *)imageUrl;
@end
FileManager.m
#import "FileManager.h"
@implementation FileManager
+ (FileManager *)shareManager
{
    static FileManager *manager = nil;
    if (manager == nil) {
        manager = [[FileManager alloc]init];
    }
    return manager;
}
// 1. 把文件夹创建在沙盒的缓存文件夹里

// 2. 需要把图片的网址变成图片名字 然后拼接成地址

// 3. 把图片写进文件 按完整地址(文件夹 + 名字)
// 返回cache文件夹的路径
- (NSString *)cachesPath
{
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSLog(@"%@", cachePath);
    return cachePath;
}
// 在cache文件夹下创建一个ImageDownload文件夹
- (NSString *)createImageDownloadFile
{
    NSString *imageDownloadPath = [[self cachesPath] stringByAppendingPathComponent:@"ImageDownload"];
    NSFileManager *manager = [NSFileManager defaultManager];
    // 判断文件夹是否存在
    if ([manager isExecutableFileAtPath:imageDownloadPath] == NO) {
        // 文件夹不存在 就创建一个
        [manager createDirectoryAtPath:imageDownloadPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return imageDownloadPath;
}
// 图片的路径 需要图片的网址 和 文件夹的路径
- (NSString *)imagesPathWithImageUrl:(NSString *)imageUrl
{
    // 转换图片的名字 把"/"转换成"_"
    NSString *imageName = [imageUrl stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
    // 拼接完整的路径
    NSString *imagePath = [[self createImageDownloadFile] stringByAppendingPathComponent:imageName];
    return imagePath;
}
// 利用路径保存图片的data
- (void)saveImageData:(NSData *)imageData imageURl:(NSString *)imageUrl
{
    // 保存的前提是要有文件夹
    //NSString *imageDownloadPath = [self createImageDownloadFile];
    // 得到图片的路径
    NSString *imagePath = [self imagesPathWithImageUrl:imageUrl];
   
    // 写文件
    [imageData writeToFile:imagePath atomically:YES];
}

@end
详情界面中加载图片的方法(两种情况)
1. 如果图片加载出来了,就把model的图片属性传过来
2. 如果图片还没有加载出来 model的图片属性为空 那么就设置观察者模式 观察这个图片属性 如果图片加载出来 就给图片赋值
//活动图片
    if (self.model.getUrlImage == nil) {
        //没有图像,下载图像
        view.activityImageView.image = [UIImage imageNamed:@"picholder"];
        [self.model imageDownload];
        // 添加一个观察者来观察图片是否已经加载出来了
        [self.model addObserver:self forKeyPath:@"getUrlImage" options:NSKeyValueObservingOptionNew context:nil];
    }else{
        view.activityImageView.image = self.model.getUrlImage;
    }
//添加观察者
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    ActivityDetailView *view = (ActivityDetailView *)self.view;
    UIImage *image = [change objectForKey:NSKeyValueChangeNewKey]; 
    view.activityImageView.image = image;  
}
二.详情界面
详情界面中对scrollView 自适应行高
- (void)adjustSubviewsWithContent:(NSString *)content
{
    //计算活动内容的高度
    CGRect frame = [content boundingRectWithSize:CGSizeMake(_titleLabel.width, 10000000) options:(NSStringDrawingUsesLineFragmentOrigin) attributes:[NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:12] forKey:NSFontAttributeName] context:nil];
    // 更改label的高度 然后再更改 scrollView的高度  显示滑动范围
    _contextLabel.height = frame.size.height;
    _bottomScrollView.contentSize = CGSizeMake(kScreenWidth, _contextLabel.bottom + 20);
}
三.登陆注销
UserManager.h
#import <Foundation/Foundation.h>
@interface UserManager : NSObject
+(UserManager *)shareUserManager;
// 传进来一个账号 把账号持久化
- (void)userName:(NSString *)userName;
// 返回账号信息
- (NSString *)userName;
- (void)password:(NSString *)passord;
- (NSString *)password;
- (void)isLogin:(BOOL)isLogin;
- (BOOL)isLogin;
@end
UserManager.m
#import "UserManager.h"
@implementation UserManager
+(UserManager *)shareUserManager
{
    static UserManager *manager = nil;
    if (manager == nil) {
        manager = [[UserManager alloc]init];
    }
    return manager;
}
// 传进来一个账号 把账号持久化
- (void)userName:(NSString *)userName
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:userName forKey:kUserName];
    // 同步数据
    [userDefaults synchronize];
}
// 返回账号信息
- (NSString *)userName
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    return [userDefaults objectForKey:kUserName];
}
- (void)password:(NSString *)passord
{
    [[NSUserDefaults standardUserDefaults] setObject:passord forKey:kPassword];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (NSString *)password
{
    return [[NSUserDefaults standardUserDefaults] objectForKey:kPassword];
}
- (void)isLogin:(BOOL)isLogin
{
    [[NSUserDefaults standardUserDefaults] setBool:isLogin forKey:kLoginState];
    [[NSUserDefaults standardUserDefaults]synchronize];
}
- (BOOL)isLogin
{
    return [[NSUserDefaults standardUserDefaults]boolForKey:kLoginState];
}

@end
四.UIAlertController
- (void)viewDidLoad {
    [super viewDidLoad];
   
    UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)];
    button.frame = CGRectMake(100, 100, 100, 100);
    [button setTitle:@"点击" forState:(UIControlStateNormal)];
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(action:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:button];
}

- (void)action:(UIButton *)button
{
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"我是alert框" preferredStyle:(UIAlertControllerStyleAlert)];
    // 创建一个按钮
    // handler  处理点击事件
    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction *action) {
        // block 回调

     NSLog(@"%@",action.title);
    }];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction *action) {
        // block 回调
        NSLog(@"%@",action.title);
    }];
    [alertVC addAction:okAction];
    [alertVC addAction:cancelAction];
   
    [alertVC addTextFieldWithConfigurationHandler:^(UITextField *textField) {
       textField.text = @"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";  
    }];
    NSArray *textFieldArray = alertVC.textFields;
    NSLog(@"%@", textFieldArray[0]); // 数组里面存放的是字典
/ <_UIAlertControllerTextField: 0x7f986a8365a0; frame = (0 0; 0 0); text = 'wwwwwwwwwwwwwwwwwwwwwwwww...'; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7f98684485f0>>/
    [self presentViewController:alertVC animated:YES completion:nil];
}

UI一揽子计划 20 (豆瓣实战之图片缓存 、豆瓣实战之详情界面(自适应行高) 、豆瓣实战之登陆注销、刘新林分享之UIAlertController)相关推荐

  1. UI一揽子计划 9 (UITableView 、UITableView 、重用机制)

    一. UITableView UITableView继承自UIScrollView,所以可以滚动 表视图的每⼀一条数据都是显示在UITableViewCell对象中 表视图可以分区显⽰示数据,每个分区 ...

  2. EasyPOI图片插入自适应行高

    easyPOI最新的文档链接地址: http://doc.wupaas.com/docs/easypoi/easypoi-1c0u4mo8p4ro8 1.模板中插入图片 ByteArrayOutput ...

  3. UI一揽子计划 21 (UICollectionView、SDWebImage第三方类库加载图片的使用、集合视图的布局UICollectionViewFlowLayout 、自定义Cell、布局协议

    Pro : SDWebImage第三方类库加载图片的使用: 1.在MRC 环境下 使用ARC 的类库: -fobjc-arc   (Build Phases  --> Compile Sourc ...

  4. UI一揽子计划 17 (image的异步加载、KVO观察者模式、KVO进行豆瓣列表界面图片的异步加载)

    把下载图片的封装起来    ImageDownloader.h #import <Foundation/Foundation.h> @protocol ImageDownloaderDel ...

  5. UI一揽子计划 6 (UIControl、UISegmentedControl、UIImageView插入数组图片、UISlider)

    一 UIControl 是所有控制类控件的基类. ·  比如UIButton    UISlider     UISegmentedControl   等只要跟控件有关系的都继承于UIControl类 ...

  6. UI一揽子计划 12 (模态ViewController、单例、通讯录实战、)

    一.模态ViewController 程序中切换⻚面,可以使⽤用UINavigationController.通过导航功能实现⻚面切 换. 某种情况下,可以使⽤视图控制器的一对⽅法实现切换⻚面 1.p ...

  7. UI一揽子计划 8 (UINavigationController 、界面通信 、NSTimer  、NSUserDefaults)

    一.UINavigationController       //  创建一个导航控制器     // 创建一个控制器作为根控制器 去管理     RootViewController *rootVC ...

  8. UI一揽子计划 11 (自定义UITableViewCell、Cell 的自适应高度)

    一. 自定义UITableViewCell 在日常的编程中,系统提供的几种Cell 样式 往往不能满足我们的需求.所以需要我们给它进行自定义样式. 自定义Cell 就是创建一个UITableViewC ...

  9. UI一揽子计划 22 (多线程概述、NSThread、NSOperationQueue 、GCD、多线程管理)

    一.多进程概述:     进程: 一个正在运行的程序 叫做一个进程     多进程: 多个程序正在运行 叫做多线程     线程: 一个进程 都会有一个或多个线程 如果只有一个 叫做主线程  主线程负 ...

最新文章

  1. cnn识别cifar10、cifar100(pytorch)
  2. puts遇到空格无法输出_输入一句英文,只包含字母和空格,如何输出这句英文中.....-黑马程序员技术交流社区...
  3. Java Object.hashCode()方法
  4. 布隆过滤器的原理、应用场景和源码分析实现
  5. 08-图7 公路村村通 (30 分)
  6. Java线程Fork/Join思想及实现
  7. pycharm如何解决新建的文件没有后缀的问题
  8. 全国计算机二级雷同卷怎么处理,信息系统项目管理师考试结束后,雷同卷怎么判定你知道吗?...
  9. 中国矿业大学python期末考试_中国矿业大学一体化网络校园网——CUMTDDNet-DrCOM网页版认证教程...
  10. Rtsp之rtp包解析
  11. ed是什么梗_《JOJO的奇妙冒险》那些梗
  12. 微信支付指纹要上传到服务器,华为即将支持微信指纹支付,同意上传至腾讯服务器!...
  13. 【转载】 乙女游戏汇总
  14. 中国人离婚率高达76.4%?这些指标背后真实的状况到底是什么样的?
  15. 小红书年货热潮|品牌场景营销新套路
  16. 私有云行业破局者 极空间家庭私有云Z4/Z2正式发布
  17. 全国各IT领军城市软件和服务外包Q群
  18. matlab 字符乱码问号,解决Linux中Matlab中文乱码问题
  19. Dvwa之SQL盲注全级别学习笔记
  20. 现在流行小程序电子名片,你跟上节奏了么?

热门文章

  1. CSS按钮样式,带代码传送门
  2. DS-SLAM的运行[TUM-1] process has died [pid 27902, exit code -11, cmd /home/jerry/catkin_ws/src/DS-SLAM/
  3. phpinfo无法显示
  4. CSP认证22_12做题记录
  5. Radius协议、EAP协议、EAP-MSCHAPv2、EAP-TLS、EAP-TTLS和EAP-PEAP
  6. Android Studio Method does not override method from its superclass
  7. 抗体纯化策略——介质篇
  8. 工作三年的Java程序员需要掌握哪些知识?
  9. vmware布署虚拟机
  10. Qt Quick系列(5)—键盘输入