如何保存相机拍摄的图片并在另一个ViewController中展示?
Hey there! Let's get your photo saving and collection view display working properly. I'll break this down into clear, actionable steps with code examples tailored to your existing implementation.
Step 1: Add Image Persistence Logic
First, we need to save the selected/captured images to your app's Documents directory (so they persist between app launches) and keep track of their filenames. Add these methods to your ViewController.m:
// Helper method to save image to Documents directory - (BOOL)saveImageToDocuments:(UIImage *)image withFileName:(NSString *)fileName { NSData *imageData = UIImageJPEGRepresentation(image, 0.8); // 0.8 balances quality and file size if (!imageData) return NO; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths firstObject]; NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName]; return [imageData writeToFile:filePath atomically:YES]; } // Helper method to get saved images filenames from UserDefaults - (NSMutableArray *)savedImageFilenames { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSMutableArray *filenames = [[defaults objectForKey:@"SavedImageFilenames"] mutableCopy]; if (!filenames) filenames = [NSMutableArray array]; return filenames; }
Now update your imagePickerController:didFinishPickingMediaWithInfo: method to save the image and update the filename list:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *chosenImage = info[UIImagePickerControllerEditedImage]; self.imageView.image = chosenImage; // Generate a unique filename using timestamp to avoid duplicates NSString *fileName = [NSString stringWithFormat:@"Photo_%f.jpg", [[NSDate date] timeIntervalSince1970]]; // Save the image and update the saved filenames list if ([self saveImageToDocuments:chosenImage withFileName:fileName]) { NSMutableArray *savedFilenames = [self savedImageFilenames]; [savedFilenames addObject:fileName]; [[NSUserDefaults standardUserDefaults] setObject:savedFilenames forKey:@"SavedImageFilenames"]; [[NSUserDefaults standardUserDefaults] synchronize]; } [picker dismissViewControllerAnimated:YES completion:NULL]; }
Step 2: Create the Photo Collection View Controller
Create a new UIViewController subclass named PhotoCollectionViewController (check "Also create XIB file" or use Storyboard based on your setup).
Configure the Collection View
- Add a
UICollectionViewto the view controller, set constraints to fill the entire view. - Set the collection view's dataSource and delegate to the view controller.
- Create a
UICollectionViewCellsubclass (e.g.,PhotoCell) with aUIImageViewinside, set constraints for the image view to fill the cell.
Code for PhotoCollectionViewController.m
#import "PhotoCollectionViewController.h" #import "PhotoCell.h" @interface PhotoCollectionViewController () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> @property (nonatomic, strong) NSMutableArray *imageFilenames; @property (nonatomic, strong) NSString *documentsDirectory; @end @implementation PhotoCollectionViewController - (void)viewDidLoad { [super viewDidLoad]; // Get path to Documents directory NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); self.documentsDirectory = [paths firstObject]; // Load saved image filenames from UserDefaults NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; self.imageFilenames = [[defaults objectForKey:@"SavedImageFilenames"] mutableCopy]; if (!self.imageFilenames) self.imageFilenames = [NSMutableArray array]; // Register the cell class (skip if using Storyboard/XIB with identifier) [self.collectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:@"PhotoCell"]; } #pragma mark - UICollectionView DataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.imageFilenames.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoCell" forIndexPath:indexPath]; // Load image from Documents directory NSString *fileName = self.imageFilenames[indexPath.row]; NSString *filePath = [self.documentsDirectory stringByAppendingPathComponent:fileName]; cell.imageView.image = [UIImage imageWithContentsOfFile:filePath]; return cell; } #pragma mark - UICollectionView DelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { // Show 3 columns with small spacing CGFloat width = (collectionView.bounds.size.width - 20) / 3; return CGSizeMake(width, width); } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(10, 10, 10, 10); } @end
Code for PhotoCell.h
#import <UIKit/UIKit.h> @interface PhotoCell : UICollectionViewCell @property (nonatomic, strong) UIImageView *imageView; @end
Code for PhotoCell.m
#import "PhotoCell.h" @implementation PhotoCell - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.imageView = [[UIImageView alloc] initWithFrame:self.bounds]; self.imageView.contentMode = UIViewContentModeScaleAspectFill; self.imageView.clipsToBounds = YES; [self.contentView addSubview:self.imageView]; } return self; } @end
Step 3: Navigate to the Collection View Controller
Add a button (or any trigger) in your original ViewController to push/present the PhotoCollectionViewController. For example, add this IBAction:
- (IBAction)showPhotoCollection:(UIButton *)sender { PhotoCollectionViewController *collectionVC = [[PhotoCollectionViewController alloc] init]; [self.navigationController pushViewController:collectionVC animated:YES]; // Use this instead if not using a navigation controller: // [self presentViewController:collectionVC animated:YES completion:nil]; }
Important Notes
- Permissions: Don't forget to add required privacy permissions to your
Info.plist:NSCameraUsageDescription(explain why your app needs camera access)NSPhotoLibraryUsageDescription(explain why your app needs photo library access)
- Image Quality: Adjust the compression value in
UIImageJPEGRepresentation(0.0 to 1.0) based on your quality/storage needs. - Scalability: For apps with many images, consider using Core Data instead of UserDefaults to store filenames for better performance and management.
内容的提问来源于stack exchange,提问作者Dhanush kumar Sivaji

