iOS open source encrypted album agony implementation (III)

Source: Internet
Author: User

Brief introduction

Although there are some good encryption album app on the market, but not the built-in ads, it is to limit the number of uploads. This paper introduces the production process of an encrypted album, which will include multiple passwords (enter different passwords to access different spaces, can be used to hide), WiFi transmission map, photo file encryption and other functions. Currently the project and the article will go forward at the same time, the project source code can be downloaded on GitHub.
Click to go to GitHub

Overview

The previous article mainly introduced the login and registration page design. This article will introduce the design and implementation of the album.

Design and implementation of photo album Interactive design

The main interface of the album is as follows.

Click the Add button to add an album folder, named after the popup Alertview, the interface is as follows.

Long press an existing album can be deleted, the interface is as follows.

File structure

The album uses the MVC design pattern, in order to facilitate the arrangement, uses the Uicollectionview, the file structure is as follows.

Model class Design

Model class for SGAlbum each model corresponding to an album, storage album name, storage path, cover map path, notice that the previous page design to add the album button also as a cell exists, so in the model class has a property description is the Add album button. In summary, the design is as follows.

typedefNs_options (Nsinteger, sgalbumtype) {Sgalbumbuttontypecommon =0, Sgalbumbuttontypeaddbutton}; @interface sgalbum : nsobject @property(nonatomic, copy)NSString*name;@property(nonatomic, copy)NSString*path;@property(nonatomic, copy)NSString*coverimageurl;@property(nonatomic,Assign) Sgalbumtype type;@end
Cell design

Each model is passed to the CollectionView cell and displayed, each cell is a Uicollectioncell subclass, its sub-view includes the background map, photo album cover, album name label three sections, as follows.

 @interface  sghomeviewcell  ()   @property  (nonatomic , weak ) uiimageview  *backgroundimageview;  @property  (nonatomic , weak ) uiimageview  *thumbimageview;  @property  (nonatomic , weak ) uilabel  *namelabel;  @end   

In order to handle the long press DELETE event, add a longpress event to the cell's Contentview, and finally the event is given to CollectionView processing, CollectionView receive the message after the display uiactionsheet to let the user confirm the operation, the selected album folder will be deleted after the operation is confirmed, and the message will continue to be passed to the controller, to reload the file, the two messages delivered through the block complete, A block is provided on the cell to CollectionView, because the block assignment is not able to get smart completion hints, so block as a private property, write a separate setter to set the callback, the code is as follows.

//Block setter- (void) Setaction: (Sghomeviewcellactionblock) Actionblock;//Private Block property@property(nonatomic, copy) Sghomeviewcellactionblock Actionblock;//Add gestureUilongpressgesturerecognizer *press = [[Uilongpressgesturerecognizer alloc] Initwithtarget: SelfAction@selector(press:)];p ress. Minimumpressduration=0.5F [ Self. ContentviewAddgesturerecognizer:press];//Gesture Handler- (voidPress: (Uilongpressgesturerecognizer *) Ges {//First album for Add button, do not handle long press DELETE event    if(GES. State! = Uigesturerecognizerstatebegan)return;if( Self. Album. Type= = Sgalbumbuttontypecommon) {if( Self. Actionblock) { Self. Actionblock(); }    }}

By overriding the setter to listen for the delivery of the model, when the model is passed to the cell, the data in the model is used to render the view, and if no cover page is provided, a default cover page is used, as shown in the code below.

-(void) Setalbum: (Sgalbum *) album {_album = Album;if (album. Type= = Sgalbumbuttontypeaddbutton) {Self. Thumbimageview. Image= [UIImage imagenamed:@"Albumaddbutton"];Self. Namelabel. Text= @"Add";} else {UIImage *thumb = [UIImage imagenamed:album. Coverimageurl?: @"Albumcover_placeholder"];Self. Thumbimageview. Image= Thumb;Self. Namelabel. Text= Album. Name;}}

To reduce the amount of code in the CollectionView, put the cell's creation and reuse logic into the cell. The code is as follows.

+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView forIndexPath:(NSIndexPath *)indexPath {    staticNSString *ID = @"SGHomeViewCell";    // register方法保证了dequeue方法无可复用时创建一个新的Cell    [collectionView registerClass:[SGHomeViewCell class] forCellWithReuseIdentifier:ID];    SGHomeViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];    return cell;}
CollectionView Design

CollectionView takes itself as a data source and is responsible for handling cell long press events, deleting albums and continuing to pass events to the controller to reload the files, the data source needs to be provided by the controller loading the sandbox files, in summary, the CollectionView needs the following attributes.

@interface SGHomeView : UICollectionView// 数据源需要的数据,由控制器负责加载@property (nonatomicstrongNSArray<SGAlbum *> *albums;// 用于向控制器二次传递Cell的长按事件,处理方式与Cell设计中一样- (void)setAction:(SGHomeViewNeedReloadActionBlock)actionBlock;@end

CollectionView Design The block callback when the data source gets the cell, the code is as follows.

-(__kindof Uicollectionviewcell *) CollectionView: (Uicollectionview *) CollectionView Cellforitematindexpath: (Nsindexpath*) Indexpath {Sghomeviewcell *cell = [Sghomeviewcell cellwithcollectionview:collectionview ForIndexPath:indexPath]; Sgalbum *album = Self. Albums[Indexpath. Row]; Cell. Album= album; WS ();//Create weakself macros to prevent circular references[Cell setaction:^{Uiactionsheet *ac = [[Uiactionsheet alloc] initwithtitle:@"Operation"Delegate Selfcancelbuttontitle:@"Cancel"destructivebuttontitle:@"Delete"Otherbuttontitles:Nil]; [AC Showinview: Self. Superview];//Currentselectalbum is used to record the current album model so that the corresponding album is deleted in the Actionsheet callback. Weakself. Currentselectalbum= album; }];returnCell;}

Because the photo album model already provides the storage path, so the deletion is very convenient, after the deletion through the block will continue to upload the event to the controller, the code is as follows.

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {    if0) {        [[NSFileManager defaultManager] removeItemAtPath:self.currentSelectAlbum.path error:nil];        if (self.actionBlock) {            self.actionBlock();        }    }}
Design of controller design file system

The controller is primarily responsible for handling the loading of files, and the storage of albums in the sandbox is described below.
The root directory of the album is the documents directory, and files for this directory can be backed up by icloud to prevent data loss. In order to distinguish between different accounts with different passwords, each password is encrypted with the name as the folder name, which acts as the album Root of the different accounts. The albums created under each account will be in the form of an entity folder in their own root directory. At the same time each album is divided into photo and thumb directories to store the original image and thumbnails, a file structure example as shown in.
The highlighted line is the root directory of an account

Because more file paths are involved, a tool class is used to manage these paths, called the SGFileUtil class, which initializes an account's root directory based on the account object, and the properties and methods used in this section are as follows.

@interface SGFileUtil : NSObject@property (nonatomicstrong) SGAccount *account;@property (nonatomicreadonlyNSString *rootPath;+ (instancetype)sharedUtil;@end

By rewriting the setter implementation of the account, the RootPath is changed according to the current one, and if the RootPath folder does not exist, the code is created as follows.

- (void)setAccount:(SGAccount *)account {    _account = account;    _rootPath = [DocumentPath stringByAppendingPathComponent:account.password];    NSFileManager *mgr = [NSFileManager defaultManager];    if (![mgr fileExistsAtPath:_rootPath isDirectory:nil]) {        [mgr createDirectoryAtPath:_rootPath withIntermediateDirectories:NO attributes:nil error:nil];    }}
The business logic of the controller

When the view loads, the CollectionView is first added to the controller view, and the CollectionView block callback is set to handle the cell long press event postback. The next step is to handle the loading of the file.

- (void) Viewdidload {[SuperViewdidload]; [ SelfSetupview]; [ SelfLoadFiles];} - (void) Setupview { Self. Title= @"Agony";    Uicollectionviewflowlayout *layout = [Uicollectionviewflowlayout new];    [Layout setscrolldirection:uicollectionviewscrolldirectionvertical]; Sghomeview *view = [[Sghomeview alloc] initWithFrame: (CGRect){0,0, [UIScreen Mainscreen]. Bounds. Size} Collectionviewlayout:layout]; View. Alwaysbouncevertical=YES; View. Delegate= Self; WS ();//To create a Weakself macro to prevent circular referencing[View setaction:^{[Weakself loadfiles]; }]; Self. Homeview= view; [ Self. ViewAddsubview:view];} - (void) LoadFiles {Sgfileutil *util = [Sgfileutil sharedutil];NSString*rootpath = Util. RootPath;Nsfilemanager*mgr = [NsfilemanagerDefaultmanager];Nsmutablearray<sgalbum *> *albums = @[]. Mutablecopy;//First album for Add album button, manually addSgalbum *addbtnalbum = [Sgalbum new]; Addbtnalbum. Type= Sgalbumbuttontypeaddbutton; [Albums Addobject:addbtnalbum];//Other albums search from the root directory of the current account    Nsarray*filenames = [Mgr Contentsofdirectoryatpath:rootpath error:Nil]; for(Nsuinteger i =0; I < FileNames. Count; i++) {NSString*filename = Filenames[i];        Sgalbum *album = [Sgalbum new]; Album. Name= FileName; Album. Path= [[Sgfileutil sharedutil]. RootPathStringbyappendingpathcomponent:filename];    [Albums Addobject:album]; } Self. Homeview. Albums= albums; [ Self. HomeviewReloaddata];}

The controller also acts as a proxy for CollectionView, handling dimensions and click events, as shown in the code below.

- (cgsize) CollectionView: (Uicollectionview *) CollectionView layout: (uicollectionviewlayout*) collectionviewlayout Sizeforitematindexpath: (Nsindexpath*) Indexpath {returnCgsizemake ( -, -);} - (uiedgeinsets) CollectionView: (Uicollectionview *) CollectionView layout: (uicollectionviewlayout*) collectionviewlayout Insetforsectionatindex: (Nsinteger) Section {returnUiedgeinsetsmake (5,Ten,5,Ten);} - (void) CollectionView: (Uicollectionview *) CollectionView Didselectitematindexpath: (Nsindexpath*) Indexpath {sgalbum *album = Self. Homeview. Albums[Indexpath. Row];//If the Add album button pops up Alertview to handle the new album event    //Otherwise launch photo browser to display album content, photo browser in the next article introduction    if(album. Type= = Sgalbumbuttontypeaddbutton) {Uialertview *alertview = [[Uialertview alloc] initwithtitle:@"New Folder"message:@"Please enter folder name"Delegate Selfcancelbuttontitle:@"Cancel"otherbuttontitles:@"OK",Nil]; Alertview. Alertviewstyle= Uialertviewstyleplaintextinput;    [Alertview show]; }Else{Sgphotobrowserviewcontroller *browser = [Sgphotobrowserviewcontroller new]; Browser. RootPath= Album. Path; [ Self. NavigationcontrollerPushviewcontroller:browser Animated:YES]; }}

Folder creation is handled in the Alertview callback, the folder name cannot be empty and cannot be duplicated, the folder is created after the check is completed, and the file is reloaded.

- (void) Alertview: (Uialertview *) Alertview Clickedbuttonatindex: (Nsinteger) Buttonindex {if(Buttonindex = =1) {NSString*foldername = [Alertview textfieldatindex:0]. Text;if(!foldername. Length) {[Mbprogresshud showerror:@"Folder Name cannot be Empty"];return; }Nsfilemanager*mgr = [NsfilemanagerDefaultmanager];NSString*folderpath = [[Sgfileutil sharedutil]. RootPathStringbyappendingpathcomponent:foldername];if([Mgr Fileexistsatpath:folderpath isdirectory:Nil]) {[Mbprogresshud showerror:@"Folder Exists"];return; } [Mgr Createdirectoryatpath:folderpath withintermediatedirectories:NOAttributesNilErrorNil]; [ SelfLoadFiles]; }}
Summarize

This article mainly introduced the album page design and implementation, the current project has completed the picture browser, welcome to follow the project, the project can be found at the beginning of the article.

iOS open source encrypted album agony implementation (III)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.