UIImageView

UIImageView

用UIImageView來顯示圖片,其contentMode屬性控制圖片如何顯示,默認(rèn)值是UIViewContentModeScaleToFill

在XIB文件中添加image view,并在其File's owner中生成IBOutlet,修改image view的Mode attribute為Aspect Fit。

UIToolbar

類似UINavigationBar,也可以在UIToolbar中添加UIBarButtonItem,不同之處是,navigation bar中只能加兩個(gè),而tool bar中有個(gè)UIBarButtonItem數(shù)組,可以添加盡量多只要能在屏幕上顯示。

在XIB中,一個(gè)UIToolBar實(shí)例默認(rèn)帶有一個(gè)UIBarButtonItem,選擇這個(gè)button,在attribute inspector中,修改identifier為Camera,會顯示一個(gè)camera icon。

camera button需要一個(gè)target和action,之前我們連接一個(gè)action方法分兩步:在代碼中聲明action方法,然后通過在XIB中將button和action方法連接起來。不過,就像outlet,也可以通過assistant editor(通過Option-click打開),來快速創(chuàng)建action并連接起來,Control-drag button到File's owner的實(shí)現(xiàn)部分。


UIImagePickerController

選擇圖片,使用UIImagePickerController,需要設(shè)置其sourceType屬性,并為其指定delegate。
sourceType告訴image picker去哪里獲得圖片:

sourceType constant description
UIImagePickerControllerSourceTypeCamera 通過相機(jī)拍攝
UIImagePickerControllerSourceTypePhotoLibrary 顯示相冊,從某個(gè)相冊選圖片
UIImagePickerControllerSourceTypeSavedPhotosAlbum 最近拍攝的圖片

在使用相機(jī)拍攝前,要先判斷設(shè)備是否支持相機(jī)。

- (IBAction)takePicture:(id)sender {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    
    // 判斷設(shè)備是否支持相機(jī)拍攝
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    } else {
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    }
    
}

設(shè)置UIImagePickerController 的代理

當(dāng)選擇一張圖片后,UIImagePickerController的代理會收到imagePickerController:didFinishPickingMediaWithInfo:消息,如果選擇cancel,沒有選擇圖片,則代理會收到imagePickerControllerDidCancel:消息。

設(shè)置image picker的代理為BKDetailViewController,在BKDetailViewController.m中聲明實(shí)現(xiàn)UINavigationControllerDelegateUIImagePickerControllerDelegate protocols

@interface BKDetailViewController () <UINavigationBarDelegate, UIImagePickerControllerDelegate>

為什么需要UINavigationControllerDelegate?UIImagePickerController繼承自其父類UINavigationController,BKDetailViewController要被設(shè)置為UIImagePickerController的delegate,所以不僅要實(shí)現(xiàn)UIImagePickerControllerDelegate protocol,還要實(shí)現(xiàn)其父類的代理協(xié)議-UINavigationBarDelegate。

- (IBAction)takePicture:(id)sender {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    
    // 判斷設(shè)備是否支持相機(jī)拍攝
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    } else {
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    }
    // 設(shè)置代理
    imagePicker.delegate = self;
}

顯示image picker

為UIImagePickerController設(shè)置好sourceType和delegate后,是時(shí)候?qū)IImagePickerController的view顯示到屏幕上。

Unlike other UIViewController subclasses you have used, an instance of UIImagePickerController is presented modally.
To present a view controller modally, you send presentViewController:animated:completion: to the UIViewController whose view is on the screen. The view controller to be presented is passed to it, and this view controller’s view slides up from the bottom of the screen.

給view controller發(fā)送**presentViewController:animated:completion: **消息,并傳遞image picker controller,image picker controller的view會從屏幕下方滑動上來顯示。

- (IBAction)takePicture:(id)sender {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    
    // 判斷設(shè)備是否支持相機(jī)拍攝
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    } else {
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    }
    // 設(shè)置代理
    imagePicker.delegate = self;
    // 顯示 image picker controller's view
    [self presentViewController:imagePicker animated:YES completion:nil];
}

獲取選中的圖片

前面提到了,當(dāng)選中了圖片后,代理會收到imagePickerController:didFinishPickingMediaWithInfo:消息,為代理添加此方法實(shí)現(xiàn):

// image picker選中圖片后,其代理收到此消息
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    // 獲得圖片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    
    self.imageView.image = image;
    
    // 移除image picker
    [self dismissViewControllerAnimated:YES completion:nil];
}

創(chuàng)建單例類來保存和查找圖片

頭文件

#import <Foundation/Foundation.h>

@interface BKImageStore : NSObject

// 靜態(tài)方法,獲得單例
+ (instancetype)sharedStore;

// 實(shí)例方法
- (void)setImage:(UIImage *)image forKey:(NSString *)key;
- (UIImage *)imageForKey:(NSString *)key;
- (void)deleteImageForKey:(NSString *)key;

@end

實(shí)現(xiàn)文件

#import "BKImageStore.h"

@interface BKImageStore()

@property (nonatomic, strong) NSMutableDictionary *dictionary;

@end

@implementation BKImageStore

// 靜態(tài)方法,調(diào)用此該來獲取單例實(shí)例
+ (instancetype)sharedStore{
    static BKImageStore *sharedStore = nil;
    if(!sharedStore){
        sharedStore = [[self alloc] initPrivate];
    }
    return sharedStore;
}

// 如果調(diào)用此方法直接拋出錯誤
- (instancetype)init{
    @throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[BKImageStore sharedStore]" userInfo:nil];
    return nil;
}

// 私有的初始化方法
- (instancetype)initPrivate{
    self = [super init];
    if (self) {
        _dictionary = [[NSMutableDictionary alloc] init];
    }
    return self;
}

// 設(shè)置指定KEY的對象
- (void)setImage:(UIImage *)image forKey:(NSString *)key{
    //[self.dictionary setObject:image forKey:key];
    self.dictionary[key] = image;
}

// 獲取指定KEY的對象
- (UIImage *)imageForKey:(NSString *)key{
    //return [self.dictionary objectForKey:key];
    return self.dictionary[key];
}

// 刪除指定KEY的對象
- (void)deleteImageForKey:(NSString *)key{
    if (!key) {
        return;
    }
    [self.dictionary removeObjectForKey:key];
}

@end

Dictionary

dictionary,可以通過快速語法(shorthand syntax)創(chuàng)建:

NSDictionary *dictionary = @{@"key": object, @"anotherKey": anotherObject};

獲取某個(gè)key的對象:

id object = dictionary[@"key"];
// same as
id object = [dictionary objectForKey:@"key"];

設(shè)置某個(gè)key的對象:

dictionary[@"key"] = object;
// same as
[dictionary setObject:object forKey:@"key"];

用UUID生成key

當(dāng)添加圖片到dictionary中,需要有一個(gè)唯一KEY,并把這個(gè)KEY設(shè)置給BKItem對象。
唯一KEY可以使用UUID,通過NSUUID來生成。

在BKItem.h中聲明一屬性來保存key:

@property (nonatomic, copy) NSString *itemKey;

在BKItem.m的初始化方法中生成UUID:

// Designated initializer (指定的構(gòu)造器,通常是參數(shù)最多的那個(gè)init方法)
- (instancetype)initWithItemName:(NSString *)name valueInDollars:(int) value serialNumber:(NSString *)sNumber{
    // Call the superclass's designated initializer
    self = [super init];
    // Did the superclass's designated initializer succeed?
    if (self) {
        // Give the instance variables initial values
        _itemName = name;
        _serialNumber = sNumber;
        _valueInDollars = value;
        // Set _dateCreated to the current date and time
        _dateCreated = [[NSDate alloc] init];
        
        // 創(chuàng)建UUID
        NSUUID *uuid = [[NSUUID alloc] init];
        NSString *key = [uuid UUIDString];
        _itemKey = key;
    }
    // Return the address of the newly initialized object
    return self;
}

當(dāng)image picker選中圖片后,將圖片保存到dictionary中

// image picker選中圖片后,其代理收到此消息
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    // 獲得圖片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    
    // 保存圖片到dictionary
    [[BKImageStore sharedStore] setImage:image forKey:self.item.itemKey];
    
    self.imageView.image = image;
    
    // 移除image picker
    [self dismissViewControllerAnimated:YES completion:nil];
}

在BKItemStore.m文件中,當(dāng)刪除BKItem時(shí),刪除與之相關(guān)的image:

#import "BKImageStore.h"

- (void)removeItem:(BKItem *)item{
    // 刪除對應(yīng)的圖片
    NSString *key = item.itemKey;
    [[BKImageStore sharedStore] deleteImageForKey:key];
    
    //[self.privateItems removeObject:item];
    [self.privateItems removeObjectIdenticalTo:item];
}

在BKDetailViewController.m中,在viewWillAppear:方法中,查找BKItem對應(yīng)的image,設(shè)置給image view.

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    
    BKItem *item = self.item;
    
    self.nameField.text = item.itemName;
    self.serialField.text = item.serialNumber;
    self.valueField.text = [NSString stringWithFormat:@"%d", item.valueInDollars];
    
    static NSDateFormatter *dateFormatter = nil;
    if(!dateFormatter){
        dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateStyle = NSDateFormatterMediumStyle;
        dateFormatter.timeStyle = NSDateFormatterNoStyle;
    }
    self.dateLabel.text = [dateFormatter stringFromDate:item.dateCreated];
    
    // 根據(jù)BKItem中的key查找圖片
    NSString *imageKey = self.item.itemKey;
    UIImage *imageToDisplay = [[BKImageStore sharedStore] imageForKey:imageKey];
    // 當(dāng)imageToDisplay為nil,UIImageView不會顯示圖片
    self.imageView.image = imageToDisplay;
}

Dismissing the keyboard

要隱藏鍵盤,需要實(shí)現(xiàn)UITextFieldDelegate protocol,并實(shí)現(xiàn)textFieldShouldReturn:方法,這樣當(dāng)點(diǎn)擊return鍵時(shí),鍵盤會隱藏。

// 當(dāng)點(diǎn)擊return鍵 隱藏鍵盤
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
}

還應(yīng)該添加更人性化的方法,當(dāng)點(diǎn)擊BKDetailViewController's view的任何地方,隱藏鍵盤

You have seen how classes like UIButton can send an action message to a target when tapped. Buttons inherit this target-action behavior from their superclass, UIControl. You are going to change the view of BKDetailViewController from an instance of UIView to an instance of UIControl so that it can handle touch events.

UIButton是UIControl的子類,UIControl都有target-action行為,當(dāng)點(diǎn)擊UIControl,會發(fā)送action消息到target。

修改BKDetailViewController的view,將其他class指定為UIControl:


然后在assistant editor中打開BKDetailViewController.m,Control-drag view到view controller的實(shí)現(xiàn):


注意上面的GIF中有個(gè)錯誤,在關(guān)聯(lián)action時(shí),在彈出框中要選擇event為Touch Up Inside.

要讓視圖隱藏鍵盤,需要調(diào)用endEditing:方法:

- (IBAction)backgroundTapped:(id)sender {
    // 隱藏鍵盤
    [self.view endEditing:YES];
}

本文是對《iOS Programming The Big Nerd Ranch Guide 4th Edition》第十一章的總結(jié)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容