MOSAD_HW3 網路訪問和本地儲存

浩男啊發表於2020-12-11

MOSAD_HW3 網路訪問和本地儲存

一、實驗目的

  • 學習使用NSURLSession或AFNetworking庫進行網路訪問

  • 學習iOS沙盒機制,進行檔案讀寫操作

二、實現功能

  • 實現兩個頁面:登陸頁和訊息頁
  • 登陸頁使用login API進行登陸,並進行成功判斷,登陸成功之後跳轉到資訊頁,並顯示登陸的個人使用者資訊
  • 訊息頁為三個button和一個tableview組成,tableview有兩個section,第一個section顯示使用者資訊,第二個section顯示圖片
    • 點選"載入"按鈕,若Cache中沒有快取的檔案,則載入網路圖片並顯示在圖片列表中,要求:圖片下載完成前,顯示loading圖示;圖片下載後,存入沙盒的Cache中
    • 點選"載入"按鈕,若Cache中已存在圖片檔案,則直接從Cache中讀取出圖片並顯示
    • 點選"清空"按鈕,清空圖片列表中的所有圖片
    • 點選"刪除快取"按鈕,刪除儲存在Cache中的圖片檔案

三、實現效果圖

  • 登陸頁:背景是動態背景(使用UIWebView實現)
    在這裡插入圖片描述
  • 資訊頁:顯示使用者資訊和圖片
    載入前:

在這裡插入圖片描述
載入中:出現載入圖示

在這裡插入圖片描述
載入後:

在這裡插入圖片描述

四、程式實現

4.0 基礎架構

本次專案基本架構使用了根控制器為UINavigationController,然後push登入頁進去,之後通過登入頁跳轉到資訊頁的方法(就是登入頁跳轉tabbarcontroller的方式)實現:

  • 根控制器:
UINavigationController * rootcontroller = [[UINavigationController alloc]init];
    self.window.rootViewController = rootcontroller;
    ViewController* loginpage = [[ViewController alloc] init];
    [rootcontroller pushViewController:loginpage animated:YES];

4.1 登陸頁

動態背景圖

首先實現登陸的背景,這裡想試一下類似於微博登陸頁的廣告推送的效果,所以學習了一下動態背景的新增方式,使用UIWebView實現了登陸頁的動態背景

  • UIWebView原本是一個可以獲取網路資料進行載入的一個View,但是由於它可以支援gif圖片的播放功能,這裡就用它來實現我們登入頁的動態背景
  • 首先獲得我們的gif圖片的NSData資料:
 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"4" ofType:@"gif"];
    NSData *gif = [NSData dataWithContentsOfFile:filePath];
  • 之後初始化我們的UIWebview,這裡要手動定義調整下我們的頁面位置,因為圖片大小可能會超過螢幕,所以要設定開始的位置為負值,並且設定ScrollView為不可滾動,否則就會變成滾動瀏覽,不符合我們的動態背景圖的要求:
    UIWebView *web = [[UIWebView  alloc] initWithFrame:CGRectMake(-70, -50, 500, 1000)];
    [web  loadData:gif MIMEType:@"image/gif" textEncodingName:@"" baseURL:nil];
    web.scrollView.scrollEnabled = NO;
    [self.view  addSubview:web];

這樣就完成了動態背景圖的加入;

使用者登入操作

  • 在點選登入button的登入按鈕中,呼叫了AFNetwork的方法來進行資料傳輸,這裡直接設定url為TA給的網址url,請求方式為GET,請求和返回資料型別為JSON型別,之後在回撥函式的success中,判斷返回的資訊是success還是fail,如果是success則跳轉進入下一個介面,如果失敗則呼叫下方的彈窗函式,彈出一個登入失敗的提示窗(PS:具體AFNetwork的使用方法就不再具體介紹了,可以看期中專案的相關部分,寫的很多很詳盡了)
#pragma mark -login
-(void)login_start{
    self.name = self.useremail.text;
    self.pass = self.password.text;
    NSLog(@"%@", self.name);
    NSLog(@"%@", self.pass);
    //AFNetwork
    AFHTTPSessionManager* manager = [[AFHTTPSessionManager alloc]init];
    NSString *url = [NSString stringWithFormat:@"http://172.18.176.202:3333/hw3/signup"];
    NSDictionary * dic = @{@"name":self.name,@"pwd":self.pass};
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager POST:url parameters:dic headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable resdic){
        //NSLog(@"login:%@",resdic);
        NSDictionary * dic = (NSDictionary *)resdic;
        NSString * str = [dic valueForKeyPath:@"msg"];
        //NSLog(@"str:%@",str);
        if ([str  isEqual: @"success"]) {
            RootTabBarController *roottabbar = [[RootTabBarController alloc]init];
            roottabbar.delegate =self;
            [self.navigationController pushViewController:roottabbar animated:YES];
        }
        if ([str  isEqual: @"fail"]) {
            [self showError:@"登陸失敗"];
        }
        
        
    } failure:^(NSURLSessionDataTask *  _Nonnull task, NSError*_Nonnull error){
        NSLog(@"fail");
    }];
}

- (void)showError:(NSString *)errorMsg {
    // 1.彈框提醒
    // 初始化對話方塊
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:errorMsg preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil]];
    // 彈出對話方塊
    [self presentViewController:alert animated:true completion:nil];
}

4.2 資訊頁

TableView

  • 我們在資訊頁要顯示使用者的個人資訊(網路請求得到)、五張圖片、URL網路請求得到,所以我們要定義一個擁有兩個section的tableview來儲存兩部分資訊
#pragma mark - tableview

- (UITableView*)tableView{
    if(_tableView == nil){
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 118, self.view.frame.size.width, self.view.frame.size.height-200) style:UITableViewStyleGrouped];
        _tableView.dataSource = self;
        _tableView.delegate = self;
        _tableView.backgroundColor = [UIColor clearColor];
       [_tableView setScrollEnabled:YES];
        //_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;//去除分割線
    }
    return _tableView;
}


#pragma mark - 重寫----設定有groupTableView有幾個分割槽
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2; // 返回值是多少既有幾個分割槽
}

#pragma mark - 重寫----設定每個分割槽有幾個單元格
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    switch (section) {
        case 0:
            return 4;
            break;
        case 1:
            return 5;
        default:
            break;
    }
    return 1;
}

這樣我們完成了tableview的建立,剩下的就是向其中新增內容

獲取使用者資訊

這裡我們通過GET請求,使用AFNetwork來獲取請求,因為是非同步網路請求,所以我們不能在tableview的載入過程中直接呼叫載入資料,這樣會先完成渲染,之後再取得資料,所以我們選擇再viewdidload中獲得資料,之後呼叫網路請求,完成之後呼叫reloaddata函式重新載入tableview:

    //AFNetwork
    AFHTTPSessionManager* manager = [[AFHTTPSessionManager alloc]init];
    NSString *url = [NSString stringWithFormat:@"http://172.18.176.202:3333/hw3/getinfo?name=MOSAD"];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable resdic){
        //NSLog(@"login:%@",resdic);
        NSDictionary * dic = (NSDictionary *)resdic;
        _namestr = [dic valueForKeyPath:@"name"];
        _levelstr = [dic valueForKeyPath:@"level"];
        _emailstr = [dic valueForKeyPath:@"email"];
        _phonestr = [dic valueForKeyPath:@"phone"];
        
        [self.tableView reloadData];
        
    } failure:^(NSURLSessionDataTask *  _Nonnull task, NSError*_Nonnull error){
        NSLog(@"fail");
    }];

載入

這次作業的唯一的難點也是有收穫的地方就是這裡了主要解決的有三個問題

  1. 點選載入後判斷cache中存在資料,則從cache載入
  2. 點選後,沒有資料,從網路請求
  3. 載入過程中顯示載入動畫
  • 首先是載入cache和網路請求,我們這裡使用NSFileManager的fileexistPath函式來判斷存在,載入則動過NSData的datafromURL來對圖片進行直接載入
  • 這裡就遇到了第一個坑,就是圖片的載入是一個同步操作,所以是執行緒阻斷的,直到圖片下載完成執行緒才會繼續,這個一開始沒有想到,所以在加入載入影像時,一直載入不進去,一開始還以為自己沒有addSubview或者add錯了,後來查詢了下NSData的載入操作才發現它竟然是同步操作hhhh
  • 所以知道它是同步操作之後就很好處理了,我們使用子執行緒來完成載入動作即可

完整載入函式程式碼如下:(至於載入從哪裡載入和是否存在檔案的判斷,期中專案完全做過了,可以去看其中專案,有比較詳細的介紹)

-(void)jiazaiphoto{
    _activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2-50, 300, 100, 100)] ;
           _activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray ;
    _activityIndicator.backgroundColor = [UIColor grayColor];
    _activityIndicator.color = [UIColor yellowColor];
           [self.view addSubview:_activityIndicator] ;
           [_activityIndicator startAnimating] ;

    
    
    [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
                    NSLog(@"下載中。。。。。");
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        NSArray* array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
                        NSString *path = array[0];
                        
                    NSFileManager * existmanager = [NSFileManager defaultManager];
                        NSString *imageFilePath = [path stringByAppendingPathComponent:@"Image1.png"];
                        NSData *data1 = [NSData dataWithContentsOfURL:[NSURL  URLWithString:@"https://hbimg.huabanimg.com/d8784bbeac692c01b36c0d4ff0e072027bb3209b106138-hwjOwX_fw658"]];// 本地
                        _image1 = [UIImage imageWithData:data1]; // 取得圖片
                        NSLog(@"get image1");
                        NSLog(@"cunrupath:%@",imageFilePath);
                        [UIImagePNGRepresentation(_image1) writeToFile:imageFilePath  atomically:YES];
                        
                        
                        imageFilePath = [path stringByAppendingPathComponent:@"Image2.png"];
                        NSData *data2 = [NSData dataWithContentsOfURL:[NSURL  URLWithString:@"https://hbimg.huabanimg.com/6215ba6f9b4d53d567795be94a90289c0151ce73400a7-V2tZw8_fw658"]];// 本地
                        _image2 = [UIImage imageWithData:data2]; // 取得圖片

                        [UIImagePNGRepresentation(_image2) writeToFile:imageFilePath  atomically:YES];
                        
                        
                        imageFilePath = [path stringByAppendingPathComponent:@"Image3.png"];
                        NSData *data3 = [NSData dataWithContentsOfURL:[NSURL  URLWithString:@"https://hbimg.huabanimg.com/834ccefee93d52a3a2694535d6aadc4bfba110cb55657-mDbhv8_fw658"]];// 本地
                        _image3 = [UIImage imageWithData:data3]; // 取得圖片

                        [UIImagePNGRepresentation(_image3) writeToFile:imageFilePath atomically:YES];
                        
                        
                        imageFilePath = [path stringByAppendingPathComponent:@"Image4.png"];
                        NSData *data4 = [NSData dataWithContentsOfURL:[NSURL  URLWithString:@"https://hbimg.huabanimg.com/f3085171af2a2993a446fe9c2339f6b2b89bc45f4e79d-LacPMl_fw658"]];// 本地
                        _image4 = [UIImage imageWithData:data4]; // 取得圖片

                        [UIImagePNGRepresentation(_image4) writeToFile:imageFilePath  atomically:YES];
                        
                        imageFilePath = [path stringByAppendingPathComponent:@"Image5.png"];
                        NSData *data5 = [NSData dataWithContentsOfURL:[NSURL  URLWithString:@"https://hbimg.huabanimg.com/e5c11e316e90656dd3164cb97de6f1840bdcc2671bdc4-vwCOou_fw658"]];// 本地
                        _image5 = [UIImage imageWithData:data5]; // 取得圖片

                        [UIImagePNGRepresentation(_image5) writeToFile:imageFilePath  atomically:YES];
                        [_activityIndicator stopAnimating] ;
                        [self.tableView reloadData];
                    }];
                }];

}

清空

  • 清空操作只要將圖片設定為空,然後reload以下即可:
-(void)qingkongphoto{
    _image1 = nil;
    _image2 = nil;
    _image3 = nil;
    _image4 = nil;
    _image5 = nil;
    [self.tableView reloadData];
}

清除快取

  • 清除快取呼叫NSFileManager的removeItemAtPath即可刪除對應路徑的快取檔案,要注意的是記得初始化為defaultmanager
-(void)deletecache{
    NSArray* array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *path = array[0];
//    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *imageFilePath1 = [path stringByAppendingPathComponent:@"Image1.png"];
    NSString *imageFilePath2 = [path stringByAppendingPathComponent:@"Image2.png"];
    NSString *imageFilePath3 = [path stringByAppendingPathComponent:@"Image3.png"];
    NSString *imageFilePath4 = [path stringByAppendingPathComponent:@"Image4.png"];
    NSString *imageFilePath5 = [path stringByAppendingPathComponent:@"Image5.png"];
    //[[NSFileManager defaultManager]  removeItemAtPath:pathFullerror:nil];
    NSLog(@"deletefilepath:%@",imageFilePath1);
    NSFileManager * filemanager= [NSFileManager defaultManager];
    NSError * error;
    [filemanager removeItemAtPath:imageFilePath1 error:&error];
    NSLog(@"error:%@",error);
    if ([filemanager removeItemAtPath:imageFilePath2 error:nil]) {
        NSLog(@"刪除成功");
    }
    //[filemanager removeItemAtPath:imageFilePath2 error:nil];
    [filemanager removeItemAtPath:imageFilePath3 error:nil];
    [filemanager removeItemAtPath:imageFilePath4 error:nil];
    [filemanager removeItemAtPath:imageFilePath5 error:nil];
}

五、個人總結

本次作業是對於網路請求的使用,由於剛做完期中專案,而且負責的就是這一部分,所以這次作業的製作還是比較簡單,要說收穫的話,就是在做載入動畫時候,發現了圖片的載入方式是同步載入,所以要開子執行緒執行。

相關文章