iOS開發——頭像設置及本地沙盒保存,圓形頭像顯示

今天來講一講iOS實際開發中,對于頭像的應用。

現在的APP中,對于頭像的設置,我們大多采用圓形頭像,并且需要支持從照相機獲取或者從相冊中選擇用戶需要的頭像,并且保存在本地或者服務器中。

在設置完頭像之后,后期如果用戶想查看頭像,一般有設置手勢,點擊將頭像按我們的設想放大。這個功能,我計劃放在后面的一篇文章里講。

本文主要講解對于頭像的設置,圓形頭像的設置、并且頭像的本地獲取已經本地化保存。

因為頭像的唯一性,所以我想大家都會考慮在頭像中使用單例設計模式。這里我們把頭像定義為 HeadsPicture 類。

類中我們的代碼可以定義如下:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface HeadsPicture : NSObject

+(instancetype)sharedHeadsPicture;
/**
 *  設置頭像
 *
 *  @param image 圖片
 */
-(void)setImage:(UIImage *)image forKey:(NSString *)key;

/**
 *  讀取圖片
 *
 */
-(UIImage *)imageForKey:(NSString *)key;

@end


我們在類中 使用了 sharedHeadsPicture 這個單例方法,也定義了一個讀取頭像圖片、以及存儲頭像圖片的方法。暫時我還是把代碼保存到了沙盒文件里,代碼中大家也可以很方便的把存儲在服務器里的頭像圖片集成進來。

HeadsPicture.m 中,代碼如下。

#import "HeadsPicture.h"

@interface HeadsPicture()

@property (nonatomic, strong) NSMutableDictionary *dictionary;

-(NSString *)imagePathForKey:(NSString *)key;

@end

@implementation HeadsPicture

+(instancetype)sharedHeadsPicture{
    
    static HeadsPicture *instance = nil;
    //確保多線程中只創建一次對象,線程安全的單例
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] initPrivate];
    });
    return instance;
}

-(instancetype)initPrivate{
    
    self = [super init];
    if (self) {
        
        _dictionary = [[NSMutableDictionary alloc] init];
        //注冊為低內存通知的觀察者
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self
               selector:@selector(clearCaches:)
                   name:UIApplicationDidReceiveMemoryWarningNotification
                 object:nil];
    }
    return self;
}

-(void)setImage:(UIImage *)image forKey:(NSString *)key{
    
    [self.dictionary setObject:image forKey:key];
    //獲取保存圖片的全路徑
    NSString *path = [self imagePathForKey:key];
    //從圖片提取JPEG格式的數據,第二個參數為圖片壓縮參數
    NSData *data = UIImageJPEGRepresentation(image, 0.5);
    //以PNG格式提取圖片數據
    //NSData *data = UIImagePNGRepresentation(image);
    
    //將圖片數據寫入文件
    [data writeToFile:path atomically:YES];
}

-(UIImage *)imageForKey:(NSString *)key{
    //return [self.dictionary objectForKey:key];
    UIImage *image = [self.dictionary objectForKey:key];
    if (!image) {
        NSString *path = [self imagePathForKey:key];
        image = [UIImage imageWithContentsOfFile:path];
        if (image) {
            
            [self.dictionary setObject:image forKey:key];
        }else{
            
            NSLog(@"Error: unable to find %@", [self imagePathForKey:key]);
        }
    }
    return image;
}

-(NSString *)imagePathForKey:(NSString *)key{
    
    NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [documentDirectories firstObject];
    return [documentDirectory stringByAppendingPathComponent:key];
}

-(void)clearCaches:(NSNotification *)n{
    
    NSLog(@"Flushing %ld images out of the cache", (unsigned long)[self.dictionary count]);
    [self.dictionary removeAllObjects];
}
@end

在上面,我們已經完成了頭像的設置與讀取。

回到界面上,我們先定義一個頭像顯示的試圖。

@property (weak, nonatomic) IBOutlet UIImageView *avatarImage;

/**
 *  設置圓形頭像屬性
 */
- (void)setCirclePhoto{
  [self.avatarImage.layer setCornerRadius:CGRectGetHeight([self.avatarImage bounds]) / 2];
  self.avatarImage.layer.masksToBounds = true;
  //可以根據需求設置邊框寬度、顏色
  self.avatarImage.layer.borderWidth = 1;
  self.avatarImage.layer.borderColor = [[UIColor blackColor] CGColor];
  //設置圖片;
  self.avatarImage.layer.contents = (id)[[UIImage imageNamed:@"avatar.png"] CGImage];
    self.avatarImage.userInteractionEnabled = YES;
}

之后完成圓形頭像的屬性設置。

最后來寫 設置頭像 按鈕背后的選擇照片的邏輯代碼。

因為是從 照相機 或者 相冊 中來讀取照片,需要使用 UIImagePickerController"圖像選擇器"

UIImagePickerController 是一種導航控制器,使用它,用戶可以打開系統的圖片選取器或者打開相機進行拍照。實現協議 UIImagePickerDelegate中定義的委托方法可以對選定后的結果進行操作,或是沒有選擇取消的操作。

具體代碼如下:

  • 首先我們先要確定、用戶需要使用相冊還是攝像頭來直接拍攝頭像。
- (IBAction)selectPhoto:(id)sender {

  UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
  imagePicker.editing = YES;
  imagePicker.delegate = self;
  /*
   如果這里allowsEditing設置為false,則下面的UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
   應該改為: UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
   也就是改為原圖像,而不是編輯后的圖像。
   */
  //允許編輯圖片
  imagePicker.allowsEditing = YES;

  /*
   這里以彈出選擇框的形式讓用戶選擇是打開照相機還是圖庫
   */
  //初始化提示框;
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"請選擇打開方式" message:nil preferredStyle:  UIAlertControllerStyleActionSheet];
  [alert addAction:[UIAlertAction actionWithTitle:@"照相機" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;

    [self presentViewController:imagePicker animated:YES completion:nil];

  }]];

  [alert addAction:[UIAlertAction actionWithTitle:@"相冊" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentViewController:imagePicker animated:YES completion:nil];
  }]];
    
  [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
    //取消;
  }]];
  //彈出提示框;
  [self presentViewController:alert animated:true completion:nil];
}

  • 之后實現 實現協議 UIImagePickerDelegate中定義的委托方法可以對選定后的結果進行操作。

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
  //通過info字典獲取選擇的照片
  UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
  //以itemKey為鍵,將照片存入ImageStore對象中
  [[HeadsPicture sharedHeadsPicture] setImage:image forKey:@"HeadsPicture"];
  //將照片放入UIImageView對象
  self.avatarImage.image = image;
  //把一張照片保存到圖庫中,此時無論是這張照片是照相機拍的還是本身從圖庫中取出的,都會保存到圖庫中;
  UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
  //壓縮圖片,如果圖片要上傳到服務器或者網絡,則需要執行該步驟(壓縮),第二個參數是壓縮比例,轉化為NSData類型;
  NSData *fileData = UIImageJPEGRepresentation(image, 1.0);
     //關閉以模態形式顯示的UIImagePickerController
  [self dismissViewControllerAnimated:YES completion:nil];

}

至此,我們已經完成了頭像的設置和本地的沙盒保存,以及圓形頭像的顯示。

至于頭像的觸摸放大等手勢功能,等下篇文章再來講解。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,764評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,179評論 4 61
  • 20170727(10/30)09班 【幸福三朵玫瑰】 昨日2朵玫瑰 今日3朵玫瑰 【幸福實修30天目標】 1、堅...
    幸福實修09班16號劉媛閱讀 179評論 0 0
  • 《藍色大海的傳說》,新上的韓劇,剛好已經完結,全部都可以下載,昨天晚上下載下來看居然可以不眠不休的看到了凌晨5點鐘...
    kasitravel閱讀 222評論 0 0
  • 認識一個人,需要緣分 了解一個人,需要時間 交往一個人,需要真誠 相處一個人,需要肚量 使用一個人,需要智慧 欣賞...
    新財思維閱讀 121評論 0 0