昨天晚上头疼,写了一部分草草的收笔了,早上起来补发一篇文章,昨天关于委托的基本使用和概念都稍微讲了一下,最开始学习委托的时候苹果官网和中文的博客文章看了不少,相似指数比较高。委托在命名要准确,最好是一看名字就知道用法,看名字就知道是干什么用的,比如说UINavigationControllerDelegate,UITableViewDelegate,这样命名不管是自己开始还是别人维护都是一个非常省心的事情,一举两得。
页面布局
先来看下效果图,这样大概知道应该实现的内容,效果如下:
这种实现,在故事板中的布局就是一个NavigationController和一个UITableView的静态表格:
其实添加的按钮是控件库中的Bar Buttom Item,将其中的Identifier设置为Add就可以是上面的效果,有一点需要说明的,添加书籍的视图中是静态单元格,需要删除控制器中多余的方法,不然无法出现效果。
Demo实现
上面跟委托有关联的地方就是保存的时候需要将数据讲给主视图去新增,而不是自己新增数据,可以通过定义一个委托实现上面的效果,具体可以参考本人的上一篇文章。需要先定义一个Book类用来存储数据:
#import <foundation/Foundation.h> #import <UIKit/UIKit.h> @interface Book : NSObject<NSCoding> @property (strong,nonatomic) UIImage *ConverPicture; @property (strong,nonatomic) NSString *BookName; @property (strong,nonatomic) NSString *Author; @property (strong,nonatomic) NSNumber *Price; @end
Book.m需要存储数据实现两个方法,具体参考之前的文章NSCoder存储数据:
// // Book.m // MySearchBar // // Created by keso on 15/2/4. // Copyright (c) 2015年 keso. All rights reserved. // #import "Book.h" @implementation Book - (void)encodeWithCoder:(NSCoder *)aCoder{ //注意这里是存储的是JPG图片的调用 [aCoder encodeObject:UIImageJPEgrepresentation(self.ConverPicture,1.0)forKey:@"ConverPicture"]; [aCoder encodeObject:_BookName forKey:@"BookName"]; [aCoder encodeObject:_Author forKey:@"Author"]; [aCoder encodeObject:_Price forKey:@"Price"]; } - (id)initWithCoder:(NSCoder *)aDecoder{ self.ConverPicture=[UIImage imageWithData:[aDecoder decodeObjectForKey:@"ConverPicture"]]; self.BookName=[aDecoder decodeObjectForKey:@"BookName"]; self.Author=[aDecoder decodeObjectForKey:@"Author"]; self.Price=[aDecoder decodeObjectForKey:@"Price"]; return self; } @end
首先来看第一个视图:RootViewController.h中的声明:
#import <UIKit/UIKit.h> #import "EditViewController.h" @interface RootViewController : UITableViewController<CustomEditViewControllerDelegate> @end
RootViewController.m中ViewDiLoad中方法加载数据:
- (void)viewDidLoad { [super viewDidLoad]; NSArray *codepath= NSSearchPathForDirectoriesInDOMains(NSDocumentDirectory, NSUserDomainMask, YES); self.BookPath= [codepath[0] stringByAppendingPathComponent:@"Book.plist"]; //这个路径暂时好像还没有存储数据的说 NSFileManager *fileManager = [NSFileManager defaultManager]; self.BookList=[[NSMutableArray alloc]init]; NSLog(@"%@",NSHomeDirectory()); if([fileManager fileExistsAtPath:_BookPath]){ self.BookList=[NSKeyedUnarchiver unarchiveObjectWithFile:self.BookPath]; } }
实现UITableView中的方法:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.BookList count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellflag = @"BookCellFlag"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellflag]; Book *book=self.BookList[indexPath.row]; [cell.textLabel setText:book.BookName]; [cell.detailTextLabel setText:book.Author]; [cell.imageView setImage:book.ConverPicture]; return cell; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([segue.identifier isEqualToString:@"editSegue"]) { EditViewController *controller = segue.destinationViewController; [controller setCustomDelegate:self]; } }
prepareForSegue用来处理新增的动作,主视图生命了自定义的委托,需要实现其方法供子视图调用:
-(void)saveBookInfo:(EditViewController *)controller{ if (self.BookList==nil) { self.BookList=[[NSMutableArray alloc]init]; } Book *book=controller.OriginalBook; [self.BookList addObject:book]; //将文件整体写入之后更新数据 [NSKeyedArchiver archiveRootObject:self.BookList toFile:self.BookPath]; [self.tableView reloadData]; }
子视图的.h文件中的声明:
#import <UIKit/UIKit.h> #import "Book.h" @class EditViewController; #pragma mark - 自定义委托 @protocol CustomEditViewControllerDelegate <NSObject> //定义一个方法,在根视图中保存数据 - (void)saveBookInfo:(EditViewController *)controller; @end @interface EditViewController : UITableViewController <UIImagePickerControllerDelegate,UIPickerViewDelegate,UIPickerViewDataSource, UINavigationControllerDelegate> @property (weak, nonatomic) id<CustomEditViewControllerDelegate> customDelegate; @property (strong,nonatomic) Book *OriginalBook; @property (weak, nonatomic) IBOutlet UIImageView *converImage; @property (weak, nonatomic) IBOutlet UITextField *bookNameText; @property (weak, nonatomic) IBOutlet UITextField *authorText; @property (weak, nonatomic) IBOutlet UITextField *priceText; @end
其中需要注意的是自定义的委托,需要传递一个子视图,先用Class声明一下使用到的类,子视图也比较简单,选择图片之前有一篇博客已经写过如何使用,其他的就是控件赋值,详细代码如下:
// // EditViewController.m // MySearchBar // // Created by keso on 15/2/4. // Copyright (c) 2015年 keso. All rights reserved. // #import "EditViewController.h" @interface EditViewController () @end @implementation EditViewController - (void)viewDidLoad { [super viewDidLoad]; // Uncomment the following line to preserve selection between presentations. // self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; } - (IBAction)chooseConverImage:(id)sender { UIImagePickerController *picker=[[UIImagePickerController alloc]init]; // 指定照片源 [picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; // 指定是否允许修改 [picker setAllowsEditing:YES]; // 指定代理 [picker setDelegate:self]; // 显示照片选择控制器 [self.navigationController presentViewController:picker animated:YES completion:nil]; } - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ UIImage *image = info[@"UIImagePickerControllerEditedImage"]; //设置图片 [self.converImage setImage:image]; [self.navigationController dismissViewControllerAnimated:YES completion:nil]; } - (IBAction)saveBook:(id)sender { if (self.OriginalBook==nil) { self.OriginalBook=[[Book alloc]init]; } //书籍名称 _OriginalBook.BookName=_bookNameText.text; //封面 _OriginalBook.ConverPicture=_converImage.image; _OriginalBook.Author=_authorText.text; _OriginalBook.Price=[[NSNumber alloc] initWithFloat:[_priceText.text floatValue]]; // 通知父视图控制器(用户列表)保存用户记录,并且返回 [_customDelegate saveBookInfo:self]; //返回到上级视图 [self.navigationController popViewControllerAnimated:YES]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
这个也算是一个委托的小Demo吧,比昨天那两个稍微好点,用到的知识点之前的博客中已经写过,如果有问题可以共同探讨,如有不当,可以评论区交流,感激不尽~