├── Screenshots
└── Untitled.gif
├── DNImagePicker
├── DNImagePicker
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Icon-29@2x.png
│ │ │ ├── Icon-29@3x.png
│ │ │ ├── Icon-40@2x.png
│ │ │ ├── Icon-40@3x.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.png
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ ├── Default@2x.png
│ │ │ ├── Default-1334@2x.png
│ │ │ ├── Default-2208@3x.png
│ │ │ ├── Default-568h@2x-2.png
│ │ │ ├── Default-2208_lan@3x.png
│ │ │ └── Contents.json
│ ├── Resources
│ │ ├── imageResources.xcassets
│ │ │ ├── Contents.json
│ │ │ └── images
│ │ │ │ ├── back_normal.imageset
│ │ │ │ ├── back_normal.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── back_highlight.imageset
│ │ │ │ ├── back_highlight.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── image_unAuthorized.imageset
│ │ │ │ ├── image_unAuthorized.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── photo_check_default.imageset
│ │ │ │ ├── photo_check_default.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── picker_alert_sigh.imageset
│ │ │ │ ├── picker_alert_sigh@2x.png
│ │ │ │ └── Contents.json
│ │ │ │ ├── photo_check_selected.imageset
│ │ │ │ ├── photo_check_selected.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── photo_full_image_selected.imageset
│ │ │ │ ├── photo_full_image_selected.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── picker_image_placeholder.imageset
│ │ │ │ ├── picker_image_placeholder@2x.png
│ │ │ │ └── Contents.json
│ │ │ │ ├── photo_full_image_unselected.imageset
│ │ │ │ ├── photo_full_image_unselected.pdf
│ │ │ │ └── Contents.json
│ │ │ │ ├── assets_placeholder_picture.imageset
│ │ │ │ ├── assets_placeholder_picture@2x.png
│ │ │ │ └── Contents.json
│ │ │ │ └── compose_photograph_background.imageset
│ │ │ │ ├── compose_photograph_background@2x.png
│ │ │ │ └── Contents.json
│ │ ├── zh-Hans.lproj
│ │ │ └── DNImagePicker.strings
│ │ └── en.lproj
│ │ │ └── DNImagePicker.strings
│ ├── ViewController.h
│ ├── DNImagePicker.h
│ ├── Classes
│ │ ├── Views
│ │ │ ├── DNBadgeLabel.h
│ │ │ ├── DNAlbumCell.h
│ │ │ ├── DNUnAuthorizedTipsView.h
│ │ │ ├── DNSendButton.h
│ │ │ ├── DNBrowserCell.h
│ │ │ ├── DNFullImageButton.h
│ │ │ ├── DNTapDetectingImageView.h
│ │ │ ├── DNAssetsViewCell.h
│ │ │ ├── DNTapDetectingImageView.m
│ │ │ ├── DNBadgeLabel.m
│ │ │ ├── DNAlbumCell.m
│ │ │ ├── DNUnAuthorizedTipsView.m
│ │ │ ├── DNSendButton.m
│ │ │ ├── DNFullImageButton.m
│ │ │ ├── DNBrowserCell.m
│ │ │ └── DNAssetsViewCell.m
│ │ ├── Controllers
│ │ │ ├── DNAlbumTableViewController.h
│ │ │ ├── DNImageFlowViewController.h
│ │ │ ├── DNImageFetchOperation.h
│ │ │ ├── DNPhotoBrowser.h
│ │ │ ├── DNImagePickerController.h
│ │ │ ├── DNImageFetchOperation.m
│ │ │ ├── DNAlbumTableViewController.m
│ │ │ ├── DNImagePickerController.m
│ │ │ ├── DNImageFlowViewController.m
│ │ │ └── DNPhotoBrowser.m
│ │ ├── Models
│ │ │ ├── DNAsset.h
│ │ │ ├── DNAsset.m
│ │ │ ├── DNAlbum.h
│ │ │ └── DNAlbum.m
│ │ ├── DNImagePickerHelper.h
│ │ └── DNImagePickerHelper.m
│ ├── AppDelegate.h
│ ├── Support
│ │ ├── UIColor+Hex.h
│ │ ├── UIView+DNImagePicker.h
│ │ ├── UIViewController+DNImagePicker.h
│ │ ├── UIColor+Hex.m
│ │ ├── UIView+DNImagePicker.m
│ │ └── UIViewController+DNImagePicker.m
│ ├── main.m
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── ViewController.m
│ └── AppDelegate.m
├── DNImagePicker.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── Dennis.xcuserdatad
│ │ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── DNImagePicker.xcscheme
│ └── project.pbxproj
└── DNImagePickerDemo
│ ├── InfoViewController.h
│ ├── CollectionViewCell.h
│ ├── CollectionViewController.h
│ ├── CollectionViewCell.m
│ ├── InfoViewController.m
│ └── CollectionViewController.m
├── README.md
└── .gitignore
/Screenshots/Untitled.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/Screenshots/Untitled.gif
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-1334@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-1334@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-2208@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-2208@3x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x-2.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-2208_lan@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Default-2208_lan@3x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_normal.imageset/back_normal.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_normal.imageset/back_normal.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_highlight.imageset/back_highlight.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_highlight.imageset/back_highlight.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/image_unAuthorized.imageset/image_unAuthorized.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/image_unAuthorized.imageset/image_unAuthorized.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_default.imageset/photo_check_default.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_default.imageset/photo_check_default.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_alert_sigh.imageset/picker_alert_sigh@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_alert_sigh.imageset/picker_alert_sigh@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_selected.imageset/photo_check_selected.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_selected.imageset/photo_check_selected.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_normal.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "back_normal.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/back_highlight.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "back_highlight.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/image_unAuthorized.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "image_unAuthorized.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_selected.imageset/photo_full_image_selected.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_selected.imageset/photo_full_image_selected.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_image_placeholder.imageset/picker_image_placeholder@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_image_placeholder.imageset/picker_image_placeholder@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_default.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "photo_check_default.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_check_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "photo_check_selected.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_unselected.imageset/photo_full_image_unselected.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_unselected.imageset/photo_full_image_unselected.pdf
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/InfoViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // InfoViewController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface InfoViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/DNImagePicker.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNImagePicker.h
3 | // ImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DNImagePickerHelper.h"
11 | #import "DNAsset.h"
12 | #import "DNAlbum.h"
13 |
14 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/assets_placeholder_picture.imageset/assets_placeholder_picture@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/assets_placeholder_picture.imageset/assets_placeholder_picture@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "photo_full_image_selected.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/compose_photograph_background.imageset/compose_photograph_background@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennisxiaoding/DNImagePicker/HEAD/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/compose_photograph_background.imageset/compose_photograph_background@2x.png
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/photo_full_image_unselected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "photo_full_image_unselected.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNBadgeLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNBadgeLabel.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/27.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNBadgeLabel : UIView
12 |
13 | @property (nonatomic, copy) NSString *title;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNAlbumTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbumTableViewController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNAlbumTableViewController : UITableViewController
12 |
13 | - (void)showUnAuthorizedTipsView;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIColor+Hex.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Hex.h
3 | // imoffice
4 | //
5 | // Created by zhanghao on 14-9-11.
6 | // Copyright (c) 2014年 IMO. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIColor (Hex)
12 |
13 | + (UIColor *)dn_hexStringToColor:(NSString *)stringToConvert;
14 | + (UIColor *)dn_colorWithHexNumber:(NSUInteger)hexColor;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNAlbumCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbumCell.h
3 | // DNImagePicker
4 | //
5 | // Created by DingXiao on 16/8/29.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNAlbumCell : UITableViewCell
12 |
13 | @property (nonatomic, strong) UIImageView *postImageView;
14 | @property (nonatomic, strong) UILabel *titleLabel;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNUnAuthorizedTipsView.h:
--------------------------------------------------------------------------------
1 | //
2 | // UnAuthorizedTipsView.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/18.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNUnAuthorizedTipsView : UIView
12 | @property (nonatomic, strong) UIImageView *imageView;
13 | @property (nonatomic, strong) UILabel *label;
14 | @end
15 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/CollectionViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewCell.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CollectionViewCell : UICollectionViewCell
12 | @property (weak, nonatomic) IBOutlet UIImageView *imageView;
13 | @property (weak, nonatomic) IBOutlet UILabel *textLabel;
14 | @end
15 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/CollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CollectionViewController : UICollectionViewController
12 |
13 | @property (nonatomic, strong) NSArray *imageArray;
14 | @property (nonatomic, assign) BOOL isFullImage;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNSendButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNSendButton.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/24.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNSendButton : UIView
12 |
13 | @property (nonatomic, copy) NSString *badgeValue;
14 |
15 | - (instancetype)initWithFrame:(CGRect)frame;
16 |
17 | - (void)addTaget:(id)target action:(SEL)action;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/zh-Hans.lproj/DNImagePicker.strings:
--------------------------------------------------------------------------------
1 | /*
2 | DNImagePicker.strings
3 | ImagePicker
4 |
5 | Created by DingXiao on 15/3/4.
6 | Copyright (c) 2015年 Dennis. All rights reserved.
7 | */
8 | "albumTitle" = "照片";
9 | "cancel" = "取消";
10 | "send" = "发送";
11 | "preview" = "预览";
12 | "fullImage" = "原图";
13 | "alertTitle" = "提示";
14 | "alertContent" = "不能超过9张图片";
15 | "alertButton" = "确定";
16 | "UnAuthorizedTip" = "请在iPhone的\"设置-隐私-照片\"选项中,\n允许%@访问你的手机相册";
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_alert_sigh.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "picker_alert_sigh@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNBrowserCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNBrowserCell.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/28.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | @class DNAsset;
11 | @class DNPhotoBrowser;
12 |
13 | @interface DNBrowserCell : UICollectionViewCell
14 |
15 | @property (nonatomic, weak, nullable) DNPhotoBrowser *photoBrowser;
16 |
17 | @property (nonatomic, strong, nullable) DNAsset *asset;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/picker_image_placeholder.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "picker_image_placeholder@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImageFlowViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNImageFlowViewController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | @class DNAlbum;
11 |
12 | @interface DNImageFlowViewController : UIViewController
13 |
14 | - (instancetype)initWithAlbumIdentifier:(NSString *)albumIdentifier;
15 |
16 | - (instancetype)initWithAblum:(DNAlbum *)album;
17 |
18 |
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/assets_placeholder_picture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "assets_placeholder_picture@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/imageResources.xcassets/images/compose_photograph_background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "compose_photograph_background@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Resources/en.lproj/DNImagePicker.strings:
--------------------------------------------------------------------------------
1 | /*
2 | DNImagePicker.strings
3 | ImagePicker
4 |
5 | Created by DingXiao on 15/3/4.
6 | Copyright (c) 2015年 Dennis. All rights reserved.
7 | */
8 | "albumTitle" = "Photos";
9 | "cancel" = "Cancel";
10 | "send" = "send";
11 | "preview" = "preview";
12 | "fullImage" = "Full Image";
13 | "alertTitle" = "Tips";
14 | "alertContent" = "Can not select more than 9 photos";
15 | "alertButton" = "OK";
16 | "UnAuthorizedTip" = "Allow %@ to access your album in \"Settings\"->\"Privacy\"->\"Photos\"";
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNFullImageButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNFullImageButton.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/2.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DNFullImageButton : UIView
12 |
13 | @property (nonatomic, assign) BOOL selected;
14 | @property (nonatomic, copy) NSString *text;
15 |
16 | - (instancetype)initWithFrame:(CGRect)frame;
17 | - (void)addTarget:(id)target action:(SEL)action;
18 | - (void)shouldAnimating:(BOOL)animate;
19 | @end
20 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/CollectionViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewCell.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "CollectionViewCell.h"
10 |
11 | @implementation CollectionViewCell
12 |
13 | - (void)awakeFromNib {
14 | [super awakeFromNib];
15 | self.textLabel.backgroundColor = [UIColor colorWithRed:0 green:162.0f/255.0f blue:255.0f/255.0f alpha:0.5];
16 | }
17 |
18 | - (void)prepareForReuse {
19 | self.imageView.image = nil;
20 | self.textLabel.text = nil;
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Models/DNAsset.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNAsset.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | @class PHAsset;
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | NS_CLASS_AVAILABLE_IOS(8.0) @interface DNAsset : NSObject
15 |
16 | @property (nonatomic, copy) NSString *assetIdentifier;
17 | @property (nonatomic, readonly) PHAsset *asset;
18 | @property (nonatomic, strong) UIImage *cacheImage;
19 |
20 | + (DNAsset *)assetWithPHAsset:(PHAsset *)asset;
21 |
22 |
23 | @end
24 |
25 | NS_ASSUME_NONNULL_END
26 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker.xcodeproj/xcuserdata/Dennis.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | DNImagePicker.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 952600AC1D2B9D4100080227
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DNImagePicker
2 | A imagePicker functioned like wechat.
3 |
4 | DNImagePicker has a swift version [DXPhotoPickerController](https://github.com/AwesomeDennis/DXPhotoPicker)
5 |
6 | Thanks [JKImagePicker](https://github.com/pjk1129/JKImagePicker)
7 | and [mwaterfall/MWPhotoBrowser](https://github.com/mwaterfall/MWPhotoBrowser)
8 |
9 | ## RELEASE
10 | * [DNImagePicker V2.0](https://github.com/AwesomeDennis/DNImagePicker/releases/tag/V2.0) supports both `AssetsLibrary` and `PhotosFramework`. When iOS > 8.0 will use `PhotosFramework` automatically.
11 |
12 | ## USEAGE
13 | * Add AssetsLibrary.framework
14 |
15 | ## DEMO
16 | 
17 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIView+DNImagePicker.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+DNImagePicker.h
3 | // JKImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (DNImagePicker)
12 |
13 | @property (nonatomic) CGFloat left;
14 | @property (nonatomic) CGFloat top;
15 | @property (nonatomic) CGFloat right;
16 | @property (nonatomic) CGFloat bottom;
17 | @property (nonatomic) CGFloat width;
18 | @property (nonatomic) CGFloat height;
19 |
20 | @property (nonatomic) CGFloat centerX;
21 | @property (nonatomic) CGFloat centerY;
22 |
23 | @property (nonatomic) CGPoint origin;
24 | @property (nonatomic) CGSize size;
25 | @end
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | #Pods/
27 |
28 | ImagePicker.xcodeproj/project.xcworkspace/xcuserdata/Dennis.xcuserdatad/UserInterfaceState.xcuserstate
29 |
30 | .DS_Store
31 |
32 | *.xcuserstate
33 |
34 | *.xcuserstate
35 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNTapDetectingImageView.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNTapDetectingImageView.h
3 | // ImagePicker
4 | //
5 | // Created by Ding Xiao on 16/1/8.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | // In order to avoid confilict to MWTapDetectingImageView, Simplifing it to this class
8 |
9 | #import
10 |
11 | @protocol DNTapDetectingImageViewDelegate
12 |
13 | @optional
14 |
15 | - (void)imageView:(UIImageView *)imageView singleTapDetected:(UITouch *)touch;
16 | - (void)imageView:(UIImageView *)imageView doubleTapDetected:(UITouch *)touch;
17 | - (void)imageView:(UIImageView *)imageView tripleTapDetected:(UITouch *)touch;
18 |
19 | @end
20 |
21 | @interface DNTapDetectingImageView : UIImageView
22 | @property (nonatomic, weak) id tapDelegate;
23 | @end
24 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImageFetchOperation.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNImageFetchOperation.h
3 | // DNImagePicker
4 | //
5 | // Created by dingxiao on 2018/10/9.
6 | // Copyright © 2018 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | @class PHAsset;
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | NS_CLASS_AVAILABLE_IOS(8.0) @interface DNImageFetchOperation : NSOperation
16 |
17 | @property (nonatomic, strong, nullable) PHAsset *asset;
18 |
19 | @property (assign, nonatomic, getter = isExecuting) BOOL executing;
20 | @property (assign, nonatomic, getter = isFinished) BOOL finished;
21 |
22 | - (instancetype)initWithAsset:(PHAsset *)asset;
23 |
24 | - (void)fetchImageWithTargetSize:(CGSize)size
25 | needHighQuality:(BOOL)isHighQuality
26 | imageResutHandler:(void (^)(UIImage * image))handler;
27 |
28 | @end
29 |
30 | NS_ASSUME_NONNULL_END
31 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNAssetsViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNAssetsViewCell.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class DNAssetsViewCell;
12 | @class DNAsset;
13 |
14 | @protocol DNAssetsViewCellDelegate
15 | @optional
16 |
17 | - (void)didSelectItemAssetsViewCell:(nonnull DNAssetsViewCell *)assetsCell;
18 | - (void)didDeselectItemAssetsViewCell:(nonnull DNAssetsViewCell *)assetsCell;
19 | @end
20 |
21 | @interface DNAssetsViewCell : UICollectionViewCell
22 |
23 | @property (nonatomic, readonly, nonnull) UIImageView *imageView;
24 | @property (nonatomic, strong, nonnull) DNAsset *asset;
25 | @property (nonatomic, assign) BOOL isSelected;
26 | @property (nonatomic, weak, nullable) id delegate;
27 |
28 | - (void)fillWithAsset:(nonnull DNAsset *)asset isSelected:(BOOL)seleted;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-29@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-29@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-40@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-40@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-60@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-60@3x.png",
37 | "scale" : "3x"
38 | }
39 | ],
40 | "info" : {
41 | "version" : 1,
42 | "author" : "xcode"
43 | }
44 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Models/DNAsset.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNAsset.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNAsset.h"
10 | #import
11 | @interface DNAsset ()
12 | @property (nonatomic, strong, nullable) PHAsset *asset;
13 | @end
14 |
15 |
16 | @implementation DNAsset
17 |
18 | - (instancetype)init {
19 | self = [super init];
20 | if (self) {
21 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarningInAssets) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
22 | }
23 | return self;
24 | }
25 |
26 |
27 | + (DNAsset *)assetWithPHAsset:(PHAsset *)asset {
28 | DNAsset *a = [[DNAsset alloc] init];
29 | if (!asset) {
30 | return a;
31 | }
32 | a.asset = asset;
33 | a.assetIdentifier = asset.localIdentifier;
34 | return a;
35 | }
36 |
37 | - (void)didReceiveMemoryWarningInAssets {
38 | _cacheImage = nil;
39 | }
40 |
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Models/DNAlbum.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbum.h
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/6.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | @class PHAssetCollection;
11 | @class PHFetchResult;
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | NS_AVAILABLE_IOS(8.0) @interface DNAlbum : NSObject
16 |
17 | + (DNAlbum *)albumWithAssetCollection:(PHAssetCollection *)collection
18 | results:(PHFetchResult *)results;
19 |
20 | /*
21 | @note use this model to store the album's 'result, 'count, 'name, 'startDate
22 | to avoid request and reserve too much times.
23 | */
24 | @property (nonatomic, strong, nullable) PHFetchResult *results;
25 |
26 | @property (nonatomic, copy, nullable) NSString *identifier;
27 |
28 | @property (nonatomic, copy, nullable) NSString *albumTitle;
29 |
30 | @property (nonatomic, assign) NSInteger count;
31 |
32 | @property (nonatomic, readonly, nullable) NSAttributedString *albumAttributedString;
33 |
34 | - (void)fetchPostImageWithSize:(CGSize)size imageResutHandler:(void (^)(UIImage *))handler;
35 |
36 | @end
37 |
38 |
39 | NS_ASSUME_NONNULL_END
40 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/InfoViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // InfoViewController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "InfoViewController.h"
10 |
11 | @interface InfoViewController ()
12 | @property (weak, nonatomic) IBOutlet UIButton *weiboButton;
13 | @property (weak, nonatomic) IBOutlet UIButton *twitterBt;
14 | - (IBAction)weiboAction:(id)sender;
15 | - (IBAction)twitterAction:(id)sender;
16 |
17 | @end
18 |
19 | @implementation InfoViewController
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | self.title = NSLocalizedString(@"infoTitle", "infotitle");
24 | // Do any additional setup after loading the view.
25 | }
26 |
27 | - (void)didReceiveMemoryWarning {
28 | [super didReceiveMemoryWarning];
29 | // Dispose of any resources that can be recreated.
30 | }
31 | - (IBAction)weiboAction:(id)sender {
32 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://weibo.com/GreatDingXiao"]];
33 | }
34 |
35 | - (IBAction)twitterAction:(id)sender {
36 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://twitter.com/Ding__Xiao"]];
37 | }
38 | @end
39 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNPhotoBrowser.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNPhotoBrowserViewController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/28.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class DNImageFlowViewController;
12 | @class DNPhotoBrowser;
13 | @class DNAsset;
14 | @protocol DNPhotoBrowserDelegate
15 |
16 | @required
17 | - (void)sendImagesFromPhotobrowser:(DNPhotoBrowser *)photoBrowse currentAsset:(DNAsset *)asset;
18 | - (NSUInteger)seletedPhotosNumberInPhotoBrowser:(DNPhotoBrowser *)photoBrowser;
19 | - (BOOL)photoBrowser:(DNPhotoBrowser *)photoBrowser currentPhotoAssetIsSeleted:(DNAsset *)asset;
20 | - (BOOL)photoBrowser:(DNPhotoBrowser *)photoBrowser seletedAsset:(DNAsset *)asset;
21 | - (void)photoBrowser:(DNPhotoBrowser *)photoBrowser deseletedAsset:(DNAsset *)asset;
22 | - (void)photoBrowser:(DNPhotoBrowser *)photoBrowser seleteFullImage:(BOOL)fullImage;
23 | @end
24 |
25 | @interface DNPhotoBrowser : UIViewController
26 |
27 | @property (nonatomic, weak) id delegate;
28 |
29 | - (instancetype)initWithPhotos:(NSArray *)photosArray
30 | currentIndex:(NSInteger)index
31 | fullImage:(BOOL)isFullImage;
32 |
33 | - (void)hideControls;
34 | - (void)toggleControls;
35 | @end
36 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "736h",
7 | "filename" : "Default-2208@3x.png",
8 | "minimum-system-version" : "8.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "736h",
16 | "filename" : "Default-2208_lan@3x.png",
17 | "minimum-system-version" : "8.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "667h",
25 | "filename" : "Default-1334@2x.png",
26 | "minimum-system-version" : "8.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "filename" : "Default@2x.png",
34 | "extent" : "full-screen",
35 | "minimum-system-version" : "7.0",
36 | "scale" : "2x"
37 | },
38 | {
39 | "extent" : "full-screen",
40 | "idiom" : "iphone",
41 | "subtype" : "retina4",
42 | "filename" : "Default-568h@2x-2.png",
43 | "minimum-system-version" : "7.0",
44 | "orientation" : "portrait",
45 | "scale" : "2x"
46 | }
47 | ],
48 | "info" : {
49 | "version" : 1,
50 | "author" : "xcode"
51 | }
52 | }
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImagePickerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNImagePickerController.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | @class ALAssetsLibrary;
13 | @class ALAssetsFilter;
14 | FOUNDATION_EXTERN NSString *kDNImagePickerStoredGroupKey;
15 | typedef NS_ENUM(NSUInteger, DNImagePickerFilterType) {
16 | DNImagePickerFilterTypeNone,
17 | DNImagePickerFilterTypePhotos,
18 | DNImagePickerFilterTypeVideos,
19 | };
20 |
21 |
22 |
23 | @class DNImagePickerController;
24 | @protocol DNImagePickerControllerDelegate
25 | @optional
26 | /**
27 | * imagePickerController‘s seleted photos
28 | *
29 | * @param imagePickerController
30 | * @param imageAssets the seleted photos packaged DNAsset type instances
31 | * @param fullImage if the value is yes, the seleted photos is full image
32 | */
33 | - (void)dnImagePickerController:(DNImagePickerController *)imagePicker
34 | sendImages:(NSArray *)imageAssets
35 | isFullImage:(BOOL)fullImage;
36 |
37 | - (void)dnImagePickerControllerDidCancel:(DNImagePickerController *)imagePicker;
38 | @end
39 |
40 |
41 | @interface DNImagePickerController : UINavigationController
42 |
43 | @property (nonatomic, assign) DNImagePickerFilterType filterType;
44 | @property (nonatomic, weak) id imagePickerDelegate;
45 |
46 | //@property (nonatomic, readonly) ALAssetsLibrary *assetsLibrary;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | DNImagePicker
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSCameraUsageDescription
28 | 需要访问您的相机
29 | NSPhotoLibraryAddUsageDescription
30 | 需要访问你的相册
31 | NSPhotoLibraryUsageDescription
32 | 为了精准找到附近可连接WiFi,请选择允许
33 | UILaunchStoryboardName
34 | LaunchScreen
35 | UIMainStoryboardFile
36 | Main
37 | UIRequiredDeviceCapabilities
38 |
39 | armv7
40 |
41 | UISupportedInterfaceOrientations
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationLandscapeLeft
45 | UIInterfaceOrientationLandscapeRight
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIViewController+DNImagePicker.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+DNImagePicker.h
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | typedef NS_ENUM(NSInteger, DNImagePickerNavigationBarPosition) {
11 | DNImagePickerNavigationBarPositionLeft,
12 | DNImagePickerNavigationBarPositionRight
13 | };
14 |
15 |
16 | @interface UIViewController (DNImagePicker)
17 |
18 | /**
19 | * 根据image创建导航栏左右item
20 | *
21 | * @param position 左右位置
22 | * @param normalImage normal状态image
23 | * @param highlightImage highlight状态image
24 | * @param action 动作
25 | */
26 | - (void)createBarButtonItemAtPosition:(DNImagePickerNavigationBarPosition)position
27 | statusNormalImage:(UIImage *)normalImage
28 | statusHighlightImage:(UIImage *)highlightImage
29 | action:(SEL)action;
30 |
31 | /**
32 | * 根据文本创建导航栏左右item
33 | *
34 | * @param position 左右位置
35 | * @param text 文本
36 | * @param action 动作
37 | */
38 | - (void)createBarButtonItemAtPosition:(DNImagePickerNavigationBarPosition)position
39 | text:(NSString *)text
40 | action:(SEL)action;
41 |
42 | /**
43 | * 根据image创建导航栏左item
44 | *
45 | * @param normalImage normal状态image
46 | * @param highlightImage highlight状态image
47 | * @param title 返回按钮title
48 | * @param action 动作
49 | */
50 | - (void)createBackBarButtonItemStatusNormalImage:(UIImage *)normalImage
51 | statusHighlightImage:(UIImage *)highlightImage
52 | withTitle:(NSString *)title
53 | action:(SEL)action;
54 |
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | #import "DNImagePickerController.h"
12 | #import "CollectionViewController.h"
13 |
14 | @interface ViewController ()
15 | @property (nonatomic, strong) NSMutableArray *assetsArray;
16 |
17 | @property (nonatomic, weak) IBOutlet UIButton *button;
18 | - (IBAction)buttonAction:(id)sender;
19 | @end
20 |
21 | @implementation ViewController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | [self.button setTitle:NSLocalizedString(@"add", @"add") forState:UIControlStateNormal];
26 | }
27 |
28 | - (void)buttonAction:(id)sender {
29 | DNImagePickerController *imagePicker = [[DNImagePickerController alloc] init];
30 | imagePicker.imagePickerDelegate = self;
31 | [self presentViewController:imagePicker animated:YES completion:nil];
32 | }
33 |
34 | #pragma mark - DNImagePickerControllerDelegate
35 |
36 | - (void)dnImagePickerController:(DNImagePickerController *)imagePickerController
37 | sendImages:(NSArray *)imageAssets
38 | isFullImage:(BOOL)fullImage {
39 | self.assetsArray = [NSMutableArray arrayWithArray:imageAssets];
40 | CollectionViewController *collectionVC = [self.storyboard instantiateViewControllerWithIdentifier:@"CollectionViewController"];
41 | collectionVC.isFullImage = fullImage;
42 | collectionVC.imageArray = imageAssets;
43 | [self.navigationController pushViewController:collectionVC animated:YES];
44 | }
45 |
46 | - (void)dnImagePickerControllerDidCancel:(DNImagePickerController *)imagePicker {
47 | [imagePicker dismissViewControllerAnimated:YES completion:nil];
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIColor+Hex.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Hex.m
3 | // imoffice
4 | //
5 | // Created by zhanghao on 14-9-11.
6 | // Copyright (c) 2014年 IMO. All rights reserved.
7 | //
8 |
9 | #import "UIColor+Hex.h"
10 |
11 | @implementation UIColor (Hex)
12 |
13 | + (UIColor *)dn_hexStringToColor:(NSString *)stringToConvert {
14 | NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
15 |
16 | if ([cString length] < 6)
17 | return [UIColor blackColor];
18 |
19 | if ([cString hasPrefix:@"0X"])
20 | cString = [cString substringFromIndex:2];
21 |
22 | if ([cString hasPrefix:@"#"])
23 | cString = [cString substringFromIndex:1];
24 |
25 | if ([cString length] != 6)
26 | return [UIColor blackColor];
27 |
28 | NSRange range;
29 | range.location = 0;
30 | range.length = 2;
31 |
32 | NSString *rString = [cString substringWithRange:range];
33 | range.location = 2;
34 |
35 | NSString *gString = [cString substringWithRange:range];
36 | range.location = 4;
37 |
38 | NSString *bString = [cString substringWithRange:range];
39 |
40 | unsigned int r, g, b;
41 |
42 | [[NSScanner scannerWithString:rString] scanHexInt:&r];
43 | [[NSScanner scannerWithString:gString] scanHexInt:&g];
44 | [[NSScanner scannerWithString:bString] scanHexInt:&b];
45 |
46 | return [UIColor colorWithRed:((float) r / 255.0f)
47 | green:((float) g / 255.0f)
48 | blue:((float) b / 255.0f)
49 | alpha:1.0f];
50 | }
51 |
52 | + (UIColor *)dn_colorWithHexNumber:(NSUInteger)hexColor {
53 | float r = ((hexColor>>16) & 0xFF) / 255.0f;
54 | float g = ((hexColor>>8) & 0xFF) / 255.0f;
55 | float b = (hexColor & 0xFF) / 255.0f;
56 | return [UIColor colorWithRed:r green:g blue:b alpha:1.0f];
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNTapDetectingImageView.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNTapDetectingImageView.m
3 | // ImagePicker
4 | //
5 | // Created by Ding Xiao on 16/1/8.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNTapDetectingImageView.h"
10 |
11 | @implementation DNTapDetectingImageView
12 |
13 | - (id)initWithFrame:(CGRect)frame {
14 | if ((self = [super initWithFrame:frame])) {
15 | self.userInteractionEnabled = YES;
16 | }
17 | return self;
18 | }
19 |
20 | - (id)initWithImage:(UIImage *)image {
21 | if ((self = [super initWithImage:image])) {
22 | self.userInteractionEnabled = YES;
23 | }
24 | return self;
25 | }
26 |
27 | - (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage {
28 | if ((self = [super initWithImage:image highlightedImage:highlightedImage])) {
29 | self.userInteractionEnabled = YES;
30 | }
31 | return self;
32 | }
33 |
34 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
35 | UITouch *touch = [touches anyObject];
36 | NSUInteger tapCount = touch.tapCount;
37 | switch (tapCount) {
38 | case 1:
39 | [self handleSingleTap:touch];
40 | break;
41 | case 2:
42 | [self handleDoubleTap:touch];
43 | break;
44 | case 3:
45 | [self handleTripleTap:touch];
46 | break;
47 | default:
48 | break;
49 | }
50 | [[self nextResponder] touchesEnded:touches withEvent:event];
51 | }
52 |
53 | - (void)handleSingleTap:(UITouch *)touch {
54 | if ([_tapDelegate respondsToSelector:@selector(imageView:singleTapDetected:)])
55 | [_tapDelegate imageView:self singleTapDetected:touch];
56 | }
57 |
58 | - (void)handleDoubleTap:(UITouch *)touch {
59 | if ([_tapDelegate respondsToSelector:@selector(imageView:doubleTapDetected:)])
60 | [_tapDelegate imageView:self doubleTapDetected:touch];
61 | }
62 |
63 | - (void)handleTripleTap:(UITouch *)touch {
64 | if ([_tapDelegate respondsToSelector:@selector(imageView:tripleTapDetected:)])
65 | [_tapDelegate imageView:self tripleTapDetected:touch];
66 | }
67 |
68 | @end
69 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/5.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePickerDemo/CollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/6.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "CollectionViewController.h"
10 | #import "CollectionViewCell.h"
11 | #import "DNImagePicker.h"
12 |
13 |
14 | #define kSizeThumbnailCollectionView ceil(self.view.frame.size.width/2)
15 |
16 | @interface CollectionViewController ()
17 | @end
18 |
19 | @implementation CollectionViewController
20 |
21 | static NSString * const reuseIdentifier = @"Cell";
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | self.title = NSLocalizedString(@"seletedImageTitle", @"seletedImage");
26 | self.collectionView.alwaysBounceVertical = YES;
27 | }
28 | #pragma mark
29 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
30 | return 1;
31 | }
32 |
33 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
34 | return self.imageArray.count;
35 | }
36 |
37 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
38 | CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
39 | DNAsset *dnasset = self.imageArray[indexPath.row];
40 | [DNImagePickerHelper fetchImageWithAsset:dnasset targetSize:CGSizeMake(kSizeThumbnailCollectionView-4, kSizeThumbnailCollectionView*1.5) imageResutHandler:^(UIImage * _Nonnull image) {
41 | cell.imageView.image = image;
42 | }];
43 | [DNImagePickerHelper fetchImageSizeWithAsset:dnasset imageSizeResultHandler:^(CGFloat imageSize, NSString * _Nonnull sizeString) {
44 | cell.textLabel.text = sizeString;
45 | }];
46 | return cell;
47 | }
48 |
49 | #pragma mark - UICollectionViewDelegateFlowLayout
50 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
51 | return CGSizeMake(kSizeThumbnailCollectionView-8, kSizeThumbnailCollectionView*1.5);
52 | }
53 |
54 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
55 | return UIEdgeInsetsMake(2, 2, 2, 2);
56 | }
57 |
58 |
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIView+DNImagePicker.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+DNImagePicker.m
3 | // JKImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "UIView+DNImagePicker.h"
10 |
11 | @implementation UIView (DNImagePicker)
12 |
13 | - (CGFloat)left {
14 | return self.frame.origin.x;
15 | }
16 |
17 | - (void)setLeft:(CGFloat)x {
18 | CGRect frame = self.frame;
19 | frame.origin.x = x;
20 | self.frame = frame;
21 | }
22 |
23 | - (CGFloat)top {
24 | return self.frame.origin.y;
25 | }
26 |
27 | - (void)setTop:(CGFloat)y {
28 | CGRect frame = self.frame;
29 | frame.origin.y = y;
30 | self.frame = frame;
31 | }
32 |
33 | - (CGFloat)right {
34 | return self.frame.origin.x + self.frame.size.width;
35 | }
36 |
37 | - (void)setRight:(CGFloat)right {
38 | CGRect frame = self.frame;
39 | frame.origin.x = right - frame.size.width;
40 | self.frame = frame;
41 | }
42 |
43 | - (CGFloat)bottom {
44 | return self.frame.origin.y + self.frame.size.height;
45 | }
46 |
47 | - (void)setBottom:(CGFloat)bottom {
48 | CGRect frame = self.frame;
49 | frame.origin.y = bottom - frame.size.height;
50 | self.frame = frame;
51 | }
52 |
53 | - (CGFloat)centerX {
54 | return self.center.x;
55 | }
56 |
57 | - (void)setCenterX:(CGFloat)centerX {
58 | self.center = CGPointMake(centerX, self.center.y);
59 | }
60 |
61 | - (CGFloat)centerY {
62 | return self.center.y;
63 | }
64 |
65 | - (void)setCenterY:(CGFloat)centerY {
66 | self.center = CGPointMake(self.center.x, centerY);
67 | }
68 |
69 | - (CGFloat)width {
70 | return self.frame.size.width;
71 | }
72 |
73 | - (void)setWidth:(CGFloat)width {
74 | CGRect frame = self.frame;
75 | frame.size.width = width;
76 | self.frame = frame;
77 | }
78 |
79 | - (CGFloat)height {
80 | return self.frame.size.height;
81 | }
82 |
83 | - (void)setHeight:(CGFloat)height {
84 | CGRect frame = self.frame;
85 | frame.size.height = height;
86 | self.frame = frame;
87 | }
88 |
89 | - (CGPoint)origin {
90 | return self.frame.origin;
91 | }
92 |
93 | - (void)setOrigin:(CGPoint)origin {
94 | CGRect frame = self.frame;
95 | frame.origin = origin;
96 | self.frame = frame;
97 | }
98 |
99 | - (CGSize)size {
100 | return self.frame.size;
101 | }
102 |
103 | - (void)setSize:(CGSize)size {
104 | CGRect frame = self.frame;
105 | frame.size = size;
106 | self.frame = frame;
107 | }
108 |
109 | @end
110 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Models/DNAlbum.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbum.m
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/7/6.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DNAlbum.h"
11 | #import "DNImagePickerHelper.h"
12 | #import "DNAsset.h"
13 |
14 | @interface DNAlbum ()
15 | @property (nonatomic, strong) NSAttributedString *albumAttributedString;
16 | @end
17 |
18 | @implementation DNAlbum
19 |
20 | - (instancetype)init {
21 | self = [super init];
22 | if (self) {
23 | _albumTitle = @"";
24 | _identifier = @"";
25 | _count = 0;
26 | }
27 | return self;
28 | }
29 |
30 | + (DNAlbum *)albumWithAssetCollection:(PHAssetCollection *)collection results:(PHFetchResult *)results{
31 | DNAlbum *album = [[DNAlbum alloc] init];
32 | if (!collection || !results) {
33 | return album;
34 | }
35 | album.count = results.count;
36 | album.results = results;
37 | album.albumTitle = collection.localizedTitle;
38 | album.identifier = collection.localIdentifier;
39 | return album;
40 | }
41 |
42 | - (void)fetchPostImageWithSize:(CGSize)size
43 | imageResutHandler:(void (^)(UIImage *))handler {
44 | [DNImagePickerHelper fetchImageWithAsset:[DNAsset assetWithPHAsset:self.results.lastObject]
45 | targetSize:size
46 | imageResutHandler:^(UIImage *postImage) {
47 | handler(postImage);
48 | }];
49 | }
50 |
51 | - (NSAttributedString *)albumAttributedString {
52 | if (!_albumAttributedString) {
53 | NSString *numberString = [NSString stringWithFormat:@" (%@)",@(self.count)];
54 | NSString *cellTitleString = [NSString stringWithFormat:@"%@%@",self.albumTitle,numberString];
55 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:cellTitleString];
56 | [attributedString setAttributes: @{
57 | NSFontAttributeName : [UIFont systemFontOfSize:16.0f],
58 | NSForegroundColorAttributeName : [UIColor blackColor],
59 | }
60 | range:NSMakeRange(0, self.albumTitle.length)];
61 | [attributedString setAttributes:@{
62 | NSFontAttributeName : [UIFont systemFontOfSize:16.0f],
63 | NSForegroundColorAttributeName : [UIColor grayColor],
64 | } range:NSMakeRange(self.albumTitle.length, numberString.length)];
65 | _albumAttributedString = attributedString;
66 | }
67 | return _albumAttributedString;
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNBadgeLabel.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNBadgeLabel.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/27.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNBadgeLabel.h"
10 | #import "UIColor+Hex.h"
11 | #import "UIView+DNImagePicker.h"
12 |
13 | @interface DNBadgeLabel ()
14 | @property (nonatomic, strong) UIView *backGroudView;
15 | @property (nonatomic, strong) UILabel *badgeLabel;
16 |
17 | @end
18 |
19 | @implementation DNBadgeLabel
20 |
21 | - (instancetype)initWithFrame:(CGRect)frame {
22 | self = [super initWithFrame:frame];
23 | if (self) {
24 | self.backgroundColor = [UIColor clearColor];
25 | [self setupViews];
26 | self.hidden = YES;
27 | }
28 | return self;
29 | }
30 |
31 | - (void)setupViews {
32 | _backGroudView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
33 | _backGroudView.backgroundColor = [UIColor dn_hexStringToColor:@"#1FB823"];
34 | _backGroudView.layer.cornerRadius = 10;
35 | [self addSubview:_backGroudView];
36 |
37 | _badgeLabel = [[UILabel alloc] initWithFrame:_backGroudView.frame];
38 | _badgeLabel.backgroundColor = [UIColor clearColor];
39 | _badgeLabel.textColor = [UIColor whiteColor];
40 | _badgeLabel.font = [UIFont systemFontOfSize:16.0f];
41 | _badgeLabel.textAlignment = NSTextAlignmentCenter;
42 | [self addSubview:_badgeLabel];
43 |
44 | _badgeLabel.userInteractionEnabled = YES;
45 | _backGroudView.userInteractionEnabled = YES;
46 | self.userInteractionEnabled = YES;
47 | }
48 |
49 | - (void)setTitle:(NSString *)title {
50 | CGRect rect = [title boundingRectWithSize:CGSizeMake(MAXFLOAT, 20) options:NSStringDrawingTruncatesLastVisibleLine attributes:nil context:nil];
51 | self.frame = CGRectMake(self.left, self.top, (rect.size.width + 9) > 20?(rect.size.width + 9):20, 20);
52 | self.backGroudView.width = self.width;
53 | self.backGroudView.height = self.height;
54 | self.badgeLabel.width = self.width;
55 | self.badgeLabel.height = self.height;
56 | self.badgeLabel.text = title;
57 |
58 | if (title.integerValue > 0) {
59 | [self show];
60 | self.backGroudView.transform =CGAffineTransformMakeScale(0, 0);
61 | [UIView animateWithDuration:0.2 animations:^{
62 | self.backGroudView.transform = CGAffineTransformMakeScale(1.1, 1.1);
63 | }
64 | completion:^(BOOL finished){
65 | [UIView animateWithDuration:0.1 animations:^{
66 | self.backGroudView.transform = CGAffineTransformMakeScale(1.0, 1.0);
67 | }];
68 | }];
69 |
70 | } else {
71 | [self hide];
72 | }
73 | }
74 |
75 | - (void)show {
76 | self.hidden = NO;
77 | }
78 |
79 | - (void)hide {
80 | self.hidden = YES;
81 | }
82 | @end
83 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNAlbumCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbumCell.m
3 | // DNImagePicker
4 | //
5 | // Created by DingXiao on 16/8/29.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNAlbumCell.h"
10 |
11 | @implementation DNAlbumCell
12 |
13 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
14 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
15 | if (self) {
16 | [self postImageView];
17 | [self titleLabel];
18 | [self addContentConstraints];
19 | }
20 | return self;
21 | }
22 |
23 | - (void)addContentConstraints {
24 | // TODO: add Constraints
25 | NSString *vflForH = @"H:|-10-[_postImageView(64)]-20-[_titleLabel]-10-|";
26 | NSString *vflForVPostImageView = @"V:|-0-[_postImageView]-0-|";
27 | NSString *vflForVtitleLabel = @"V:|-1-[_titleLabel]-1-|";
28 | NSArray *contraintsH = [NSLayoutConstraint
29 | constraintsWithVisualFormat:vflForH
30 | options:0
31 | metrics:nil
32 | views:NSDictionaryOfVariableBindings(_postImageView,_titleLabel)];
33 | NSArray *contraintsVPostImageView = [NSLayoutConstraint
34 | constraintsWithVisualFormat:vflForVPostImageView
35 | options:0
36 | metrics:nil
37 | views:NSDictionaryOfVariableBindings(_postImageView)];
38 | NSArray *contraintsVtitleLabel = [NSLayoutConstraint
39 | constraintsWithVisualFormat:vflForVtitleLabel
40 | options:0
41 | metrics:nil
42 | views:NSDictionaryOfVariableBindings(_titleLabel)];
43 | [self.contentView addConstraints:contraintsH];
44 | [self.contentView addConstraints:contraintsVPostImageView];
45 | [self.contentView addConstraints:contraintsVtitleLabel];
46 | }
47 |
48 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
49 | [super setSelected:selected animated:animated];
50 | }
51 |
52 | - (UIImageView *)postImageView {
53 | if (!_postImageView) {
54 | _postImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
55 | [_postImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
56 | [self.contentView addSubview:_postImageView];
57 | }
58 | return _postImageView;
59 | }
60 |
61 | - (UILabel *)titleLabel {
62 | if (!_titleLabel) {
63 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
64 | [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
65 | _titleLabel.backgroundColor = [UIColor clearColor];
66 | _titleLabel.textAlignment = NSTextAlignmentLeft;
67 | [self.contentView addSubview:_titleLabel];
68 | }
69 | return _titleLabel;
70 | }
71 | @end
72 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/DNImagePickerHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNImagePickerHelper.h
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/8/23.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | typedef NS_ENUM(NSUInteger, DNAlbumAuthorizationStatus) {
13 | // User has not yet made a choice with regards to this application
14 | DNAlbumAuthorizationStatusNotDetermined = 0,
15 | // This application is not authorized to access photo data.
16 | // The user cannot change this application’s status, possibly due to active restrictions
17 | // such as parental controls being in place.
18 | DNAlbumAuthorizationStatusRestricted,
19 | // User has explicitly denied this application access to photos data.
20 | DNAlbumAuthorizationStatusDenied,
21 | // User has authorized this application to access photos data.
22 | DNAlbumAuthorizationStatusAuthorized
23 | };
24 |
25 | typedef NS_ENUM(NSUInteger, DNImagePickerFitlerType) {
26 | DNImagePickerFitlerTypeUnknown = 0,
27 | DNImagePickerFitlerTypeImage = 1,
28 | DNImagePickerFitlerTypeVideo = 2,
29 | DNImagePickerFitlerTypeAudio = 3,
30 | };
31 |
32 |
33 | @class DNAlbum;
34 | @class DNAsset;
35 |
36 | NS_ASSUME_NONNULL_BEGIN
37 | FOUNDATION_EXTERN NSString * const DNImagePickerPhotoLibraryChangedNotification;
38 | NS_CLASS_AVAILABLE_IOS(8.0) @interface DNImagePickerHelper : NSObject
39 |
40 | + (instancetype)sharedHelper;
41 |
42 |
43 | + (void)cancelFetchWithAssets:(DNAsset *)asset;
44 |
45 | /**
46 | * Returns information about your app’s authorization for accessing the user’s Photos library.
47 | The current authorization status. See `DNAlbumAuthorizationStatus`.
48 | *
49 | * @return The current authorization status.
50 | */
51 | + (DNAlbumAuthorizationStatus)authorizationStatus;
52 |
53 | /**
54 | * Fetch the albumlist
55 | *
56 | */
57 | + (void)requestAlbumListWithCompleteHandler:(void(^)(NSArray* anblumList))competeHandler;
58 |
59 | /**
60 | * Fetch the album which is stored by identifier; if not stored, it'll return the album without anything.
61 | *
62 | * @return the stored album
63 | */
64 | + (void)requestCurrentAblumWithCompleteHandler:(void(^)(DNAlbum * album))completeHandler;
65 |
66 |
67 | /**
68 | fetch images in the specific ablum
69 |
70 | @param album target album
71 | @param completeHandler callbacks with imageArray
72 | */
73 | + (void)fetchImageAssetsInAlbum:(DNAlbum *)album completeHandler:(void(^)(NSArray* imageArray))completeHandler;
74 |
75 |
76 | + (void)fetchImageSizeWithAsset:(DNAsset *)asset
77 | imageSizeResultHandler:(void (^)(CGFloat imageSize, NSString * sizeString))handler;
78 |
79 |
80 | /**
81 | fetch Image with assets
82 |
83 | @param asset target assets
84 | @param targetSize target size
85 | @param isHighQuality is need highQuality
86 | @param handler callback with image
87 | */
88 | + (void)fetchImageWithAsset:(DNAsset *)asset
89 | targetSize:(CGSize)targetSize
90 | needHighQuality:(BOOL)isHighQuality
91 | imageResutHandler:(void (^)(UIImage * image))handler;
92 | /**
93 | fetch Image with assets
94 | same as `fetchImageWithAsset:targetSize:needHighQuality:imageResutHandler:` param `isHighQuality` is NO
95 | */
96 | + (void)fetchImageWithAsset:(DNAsset *)asset
97 | targetSize:(CGSize)targetSize
98 | imageResutHandler:(void (^)(UIImage *))handler;
99 |
100 | // storeage
101 | + (void)saveAblumIdentifier:(NSString *)identifier;
102 |
103 | + (NSString *)albumIdentifier;
104 |
105 |
106 | @end
107 | NS_ASSUME_NONNULL_END
108 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImageFetchOperation.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNImageFetchOperation.m
3 | // DNImagePicker
4 | //
5 | // Created by dingxiao on 2018/10/9.
6 | // Copyright © 2018 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNImageFetchOperation.h"
10 | #import
11 | #import
12 |
13 | typedef void(^DNImageResultHandler)(UIImage *image);
14 |
15 | @interface DNImageFetchOperation ()
16 | @property (nonatomic, assign) PHImageRequestID requestID;
17 | @property (nonatomic, assign) CGSize targetSize;
18 | @property (nonatomic, assign) BOOL isHighQuality;
19 | @property (nonatomic, copy) DNImageResultHandler resultHandler;
20 | @end
21 |
22 | @implementation DNImageFetchOperation
23 |
24 | @synthesize executing = _executing;
25 | @synthesize finished = _finished;
26 |
27 | - (instancetype)initWithAsset:(PHAsset *)asset {
28 | self = [super init];
29 | if (self) {
30 | _asset = asset;
31 | _executing = NO;
32 | _finished = NO;
33 | }
34 | return self;
35 | }
36 |
37 | - (void)fetchImageWithTargetSize:(CGSize)size
38 | needHighQuality:(BOOL)isHighQuality
39 | imageResutHandler:(void (^)(UIImage * _Nonnull))handler {
40 | self.targetSize = size;
41 | self.isHighQuality = isHighQuality;
42 | self.resultHandler = handler;
43 | }
44 |
45 | - (void)start {
46 | @synchronized (self) {
47 | if (self.isCancelled) {
48 | self.finished = YES;
49 | [self reset];
50 | return;
51 | }
52 | if (!self.asset) {
53 | self.finished = YES;
54 | [self reset];
55 | return;
56 | }
57 | PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
58 | if (self.isHighQuality) {
59 | options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
60 | } else {
61 | options.resizeMode = PHImageRequestOptionsResizeModeExact;
62 | }
63 | [[PHImageManager defaultManager] requestImageForAsset:self.asset targetSize:self.targetSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
64 | dispatch_async(dispatch_get_main_queue(), ^{
65 | if (self.resultHandler) {
66 | self.resultHandler(result);
67 | }
68 | [self done];
69 | });
70 | }];
71 | self.executing = YES;
72 | }
73 | }
74 |
75 | - (void)cancel {
76 | @synchronized (self) {
77 | if (self.isFinished) return;
78 | [super cancel];
79 |
80 | if (self.asset && self.requestID != PHInvalidImageRequestID) {
81 | [[PHCachingImageManager defaultManager] cancelImageRequest:self.requestID];
82 | if (self.isExecuting) self.executing = NO;
83 | if (!self.isFinished) self.finished = YES;
84 | }
85 | [self reset];
86 | }
87 | }
88 |
89 | - (void)done {
90 | self.finished = YES;
91 | self.executing = NO;
92 | [self reset];
93 | }
94 |
95 | - (void)reset {
96 | self.asset = nil;
97 | }
98 |
99 | - (void)setFinished:(BOOL)finished {
100 | [self willChangeValueForKey:@"isFinished"];
101 | _finished = finished;
102 | [self didChangeValueForKey:@"isFinished"];
103 | }
104 |
105 | - (void)setExecuting:(BOOL)executing {
106 | [self willChangeValueForKey:@"isExecuting"];
107 | _executing = executing;
108 | [self didChangeValueForKey:@"isExecuting"];
109 | }
110 |
111 | - (BOOL)isConcurrent {
112 | return YES;
113 | }
114 |
115 |
116 | @end
117 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker.xcodeproj/xcuserdata/Dennis.xcuserdatad/xcschemes/DNImagePicker.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNUnAuthorizedTipsView.m:
--------------------------------------------------------------------------------
1 | //
2 | // UnAuthorizedTipsView.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/18.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNUnAuthorizedTipsView.h"
10 |
11 | @implementation DNUnAuthorizedTipsView
12 |
13 | - (instancetype)initWithFrame:(CGRect)frame {
14 | self = [super initWithFrame:frame];
15 | if (self) {
16 | [self imageView];
17 | [self label];
18 | [self addContentConstraints];
19 | }
20 | return self;
21 | }
22 |
23 | - (void)addContentConstraints {
24 | NSDictionary *imageViewMetric = @{@"imageLength":@130,@"labelHeight":@60};
25 | NSString *vflV = @"V:|-120-[_imageView(imageLength)]-30-[_label(<=labelHeight@750)]";
26 | NSString *vflH = @"H:|-33-[_label]-33-|";
27 | NSArray *contstraintsV = [NSLayoutConstraint constraintsWithVisualFormat:vflV options:0 metrics:imageViewMetric views:NSDictionaryOfVariableBindings(_imageView,_label)];
28 | NSArray *contstraintsH = [NSLayoutConstraint constraintsWithVisualFormat:vflH options:0 metrics:imageViewMetric views:NSDictionaryOfVariableBindings(_label)];
29 | NSLayoutConstraint *imageViewContstraintsCenterX = [NSLayoutConstraint
30 | constraintWithItem:self.imageView
31 | attribute:NSLayoutAttributeCenterX
32 | relatedBy:NSLayoutRelationEqual
33 | toItem:self
34 | attribute:NSLayoutAttributeCenterX
35 | multiplier:1.0f
36 | constant:0];
37 | NSLayoutConstraint *imageViewConstraintsWidth = [NSLayoutConstraint
38 | constraintWithItem:self.imageView
39 | attribute:NSLayoutAttributeWidth
40 | relatedBy:NSLayoutRelationEqual
41 | toItem:nil
42 | attribute:NSLayoutAttributeNotAnAttribute
43 | multiplier:0
44 | constant:130.0f];
45 | [self addConstraints:@[imageViewConstraintsWidth,imageViewContstraintsCenterX]];
46 | [self addConstraints:contstraintsV];
47 | [self addConstraints:contstraintsH];
48 | }
49 |
50 | #pragma mark - getter
51 | - (UIImageView *)imageView {
52 | if (!_imageView) {
53 | _imageView = [UIImageView new];
54 | _imageView.image = [UIImage imageNamed:@"image_unAuthorized"];
55 | [_imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
56 | [self addSubview:_imageView];
57 | }
58 | return _imageView;
59 | }
60 |
61 | - (UILabel *)label {
62 | if (!_label) {
63 | _label = [UILabel new];
64 | [_label setTranslatesAutoresizingMaskIntoConstraints:NO];
65 | NSString *text = NSLocalizedStringFromTable(@"UnAuthorizedTip", @"DNImagePicker", @"UnAuthorizedTip");
66 | NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
67 | NSString*appName =[infoDict objectForKey:@"CFBundleDisplayName"]
68 | ;
69 | NSString *tipsString = [NSString stringWithFormat:text,appName];
70 | _label.text = tipsString;
71 | _label.textColor = [UIColor blackColor];
72 | _label.font = [UIFont systemFontOfSize:14.0f];
73 | _label.textAlignment = NSTextAlignmentCenter;
74 | _label.numberOfLines = 0;
75 | _label.backgroundColor = [UIColor clearColor];
76 | _label.lineBreakMode = NSLineBreakByTruncatingTail;
77 | [self addSubview:_label];
78 | }
79 | return _label;
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNAlbumTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNAlbumTableViewController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNAlbumTableViewController.h"
10 | #import "DNImagePickerController.h"
11 | #import "DNImageFlowViewController.h"
12 | #import "DNAlbumCell.h"
13 | #import "UIViewController+DNImagePicker.h"
14 | #import "DNUnAuthorizedTipsView.h"
15 | #import "DNImagePickerHelper.h"
16 | #import "DNAlbum.h"
17 |
18 | static NSString* const dnalbumTableViewCellReuseIdentifier = @"dnalbumTableViewCellReuseIdentifier";
19 |
20 | @interface DNAlbumTableViewController ()
21 | @property (nonatomic, strong) NSArray *albumArray;
22 | @end
23 |
24 | @implementation DNAlbumTableViewController
25 |
26 | #pragma mark - life cycle
27 |
28 | - (void)viewDidLoad {
29 | [super viewDidLoad];
30 | [self setupView];
31 | [self reloadTableView];
32 | }
33 |
34 | #pragma mark - public
35 |
36 | - (void)reloadTableView {
37 | [DNImagePickerHelper requestAlbumListWithCompleteHandler:^(NSArray * _Nonnull anblumList) {
38 | if (anblumList) {
39 | self.albumArray = [anblumList copy];
40 | [self.tableView reloadData];
41 | }
42 | }];
43 | }
44 |
45 | #pragma mark - mark setup Data and View
46 | - (void)setupView {
47 | self.title = NSLocalizedStringFromTable(@"albumTitle", @"DNImagePicker", @"photos");
48 | [self createBarButtonItemAtPosition:DNImagePickerNavigationBarPositionRight
49 | text:NSLocalizedStringFromTable(@"cancel", @"DNImagePicker", @"取消")
50 | action:@selector(cancelAction:)];
51 |
52 | [self.tableView registerClass:[DNAlbumCell class] forCellReuseIdentifier:dnalbumTableViewCellReuseIdentifier];
53 | UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
54 | self.tableView.tableFooterView = view;
55 | }
56 |
57 |
58 | #pragma mark - ui actions
59 | - (void)cancelAction:(id)sender {
60 | DNImagePickerController *navController = [self dnImagePickerController];
61 | if (navController && [navController.imagePickerDelegate respondsToSelector:@selector(dnImagePickerControllerDidCancel:)]) {
62 | [navController.imagePickerDelegate dnImagePickerControllerDidCancel:navController];
63 | }
64 | }
65 |
66 | #pragma mark - getter/setter
67 |
68 | - (DNImagePickerController *)dnImagePickerController {
69 | if (!self.navigationController
70 | ||
71 | ![self.navigationController isKindOfClass:[DNImagePickerController class]])
72 | {
73 | NSAssert(false, @"check the navigation controller");
74 | }
75 | return (DNImagePickerController *)self.navigationController;
76 | }
77 |
78 | - (void)showUnAuthorizedTipsView {
79 | DNUnAuthorizedTipsView *view = [[DNUnAuthorizedTipsView alloc] initWithFrame:self.tableView.frame];
80 | self.tableView.backgroundView = view;
81 | }
82 |
83 | #pragma mark - Table view data source
84 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
85 | return self.albumArray.count;
86 | }
87 |
88 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
89 | DNAlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:dnalbumTableViewCellReuseIdentifier forIndexPath:indexPath];
90 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
91 | DNAlbum *album = self.albumArray[indexPath.row];
92 | cell.titleLabel.attributedText = album.albumAttributedString;
93 | [album fetchPostImageWithSize:CGSizeMake(60, 60) imageResutHandler:^(UIImage * _Nullable postImage) {
94 | if (postImage) {
95 | cell.postImageView.image = postImage;
96 | } else {
97 | cell.postImageView.image = [UIImage imageNamed:@"assets_placeholder_picture"];
98 | }
99 | }];
100 | return cell;
101 | }
102 |
103 | - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
104 | return 64;
105 | }
106 |
107 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
108 | return 64;
109 | }
110 |
111 | #pragma mark - tableView delegate
112 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
113 | DNAlbum *album = self.albumArray[indexPath.row];
114 | DNImageFlowViewController *imageFlowViewController = [[DNImageFlowViewController alloc] initWithAblum:album];
115 | [self.navigationController pushViewController:imageFlowViewController animated:YES];
116 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
117 | }
118 |
119 | @end
120 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Support/UIViewController+DNImagePicker.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+DNImagePicker.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 dennis. All rights reserved.
7 | //
8 |
9 | #import "UIViewController+DNImagePicker.h"
10 | #import "UIColor+Hex.h"
11 |
12 | @implementation UIViewController (DNImagePicker)
13 | - (void)createBarButtonItemAtPosition:(DNImagePickerNavigationBarPosition)position statusNormalImage:(UIImage *)normalImage statusHighlightImage:(UIImage *)highlightImage action:(SEL)action {
14 |
15 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
16 | UIEdgeInsets insets = UIEdgeInsetsZero;
17 | switch (position) {
18 | case DNImagePickerNavigationBarPositionLeft:
19 | insets = UIEdgeInsetsMake(0, -20, 0, 20);
20 | break;
21 | case DNImagePickerNavigationBarPositionRight:
22 | insets = UIEdgeInsetsMake(0, 13, 0, -13);
23 | break;
24 | default:
25 | break;
26 | }
27 |
28 | [button setImageEdgeInsets:insets];
29 | [button setFrame:CGRectMake(0, 0, 44, 44)];
30 | [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
31 | [button setImage:normalImage forState:UIControlStateNormal];
32 | [button setImage:highlightImage forState:UIControlStateHighlighted];
33 |
34 | UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
35 | switch (position) {
36 | case DNImagePickerNavigationBarPositionLeft:
37 | self.navigationItem.leftBarButtonItem = barButtonItem;
38 | break;
39 | case DNImagePickerNavigationBarPositionRight:
40 | self.navigationItem.rightBarButtonItem = barButtonItem;
41 | break;
42 | default:
43 | break;
44 | }
45 | }
46 |
47 | - (void)createBarButtonItemAtPosition:(DNImagePickerNavigationBarPosition)position text:(NSString *)text action:(SEL)action {
48 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
49 |
50 | UIEdgeInsets insets = UIEdgeInsetsZero;
51 | switch (position) {
52 | case DNImagePickerNavigationBarPositionLeft:
53 | insets = UIEdgeInsetsMake(0, -49 + 26, 0, 19);
54 | break;
55 | case DNImagePickerNavigationBarPositionRight:
56 | insets = UIEdgeInsetsMake(0, 49 - 26, 0, -19);
57 | break;
58 | default:
59 | break;
60 | }
61 |
62 | [button setTitleEdgeInsets:insets];
63 | [button setFrame:CGRectMake(0, 0, 64, 30)];
64 | [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
65 | [button setTitle:text forState:UIControlStateNormal];
66 | button.titleLabel.font = [UIFont systemFontOfSize:15.0f];
67 | [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
68 | [button setTitleColor:[UIColor dn_hexStringToColor:@"#808080"] forState:UIControlStateHighlighted];
69 |
70 | UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
71 | switch (position) {
72 | case DNImagePickerNavigationBarPositionLeft:
73 | self.navigationItem.leftBarButtonItem = barButtonItem;
74 | break;
75 | case DNImagePickerNavigationBarPositionRight:
76 | self.navigationItem.rightBarButtonItem = barButtonItem;
77 | break;
78 | default:
79 | break;
80 | }
81 | }
82 |
83 | - (void)createBackBarButtonItemStatusNormalImage:(UIImage *)normalImage statusHighlightImage:(UIImage *)highlightImage withTitle:(NSString *)title action:(SEL)action {
84 |
85 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
86 | [button setFrame:CGRectMake(0, 0, 84, 44)];
87 | [button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
88 | [button setTitleColor:[UIColor dn_hexStringToColor:@"#808080"] forState:UIControlStateHighlighted];
89 | UIEdgeInsets imageInsets = UIEdgeInsetsMake(0, -20, 0, 60);
90 | UIEdgeInsets titleInsets = UIEdgeInsetsMake(0, -45, 0, -15);
91 | [button.titleLabel setFont:[UIFont systemFontOfSize:15.0f]];
92 | [button setImageEdgeInsets:imageInsets];
93 | [button setTitleEdgeInsets:titleInsets];
94 | button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
95 |
96 | [button setTitle:title forState:UIControlStateNormal];
97 | [button setTitle:title forState:UIControlStateHighlighted];
98 | [button setImage:normalImage forState:UIControlStateNormal];
99 | [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
100 |
101 | UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
102 |
103 | self.navigationItem.leftBarButtonItem = barButtonItem;
104 | }
105 |
106 | @end
107 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNSendButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNSendButton.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/24.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNSendButton.h"
10 | #import "UIView+DNImagePicker.h"
11 | #import "UIColor+Hex.h"
12 | #define kSendButtonFont [UIFont systemFontOfSize:15]
13 | static NSString *const dnSendButtonTintNormalColor = @"#1FB823";
14 | //static NSString *const dnSendButtonTintAbnormalColor = @"#C9DCCA";
15 | static NSString *const dnSendButtonTintAbnormalColor = @"#C9EFCA";
16 |
17 | static CGFloat const kSendButtonTextWitdh = 38.0f;
18 |
19 | @interface DNSendButton ()
20 | @property (nonatomic, strong) UILabel *badgeValueLabel;
21 | @property (nonatomic, strong) UIView *backGroudView;
22 | @property (nonatomic, strong) UIButton *sendButton;
23 |
24 | @end
25 |
26 | @implementation DNSendButton
27 |
28 | - (instancetype)initWithFrame:(CGRect)frame
29 | {
30 | self = [super initWithFrame:frame];
31 | if (self) {
32 | self.left = 0;
33 | self.right = 0;
34 | self.top = 0;
35 | self.bottom = 0;
36 | self.width = 58;
37 | self.height = 26;
38 | [self setupViews];
39 | self.badgeValue = @"0";
40 | }
41 | return self;
42 | }
43 |
44 | - (void)setupViews
45 | {
46 | _backGroudView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
47 | _backGroudView.centerY = self.centerY;
48 | _backGroudView.backgroundColor = [UIColor dn_hexStringToColor:dnSendButtonTintNormalColor];
49 | _backGroudView.layer.cornerRadius = _backGroudView.height/2;
50 | [self addSubview:_backGroudView];
51 |
52 | _badgeValueLabel = [[UILabel alloc] initWithFrame:_backGroudView.frame];
53 | _badgeValueLabel.backgroundColor = [UIColor clearColor];
54 | _badgeValueLabel.textColor = [UIColor whiteColor];
55 | _badgeValueLabel.font = [UIFont systemFontOfSize:15.0f];
56 | _badgeValueLabel.textAlignment = NSTextAlignmentCenter;
57 | [self addSubview:_badgeValueLabel];
58 |
59 | _sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
60 | _sendButton.frame = CGRectMake(0, 0, self.width, self.height);
61 | [_sendButton setTitle:NSLocalizedStringFromTable(@"send", @"DNImagePicker", @"发送")
62 | forState:UIControlStateNormal];
63 | [_sendButton setTitleColor:[UIColor dn_hexStringToColor:dnSendButtonTintNormalColor] forState:UIControlStateNormal];
64 | [_sendButton setTitleColor:[UIColor dn_hexStringToColor:dnSendButtonTintAbnormalColor] forState:UIControlStateHighlighted];
65 | [_sendButton setTitleColor:[UIColor dn_hexStringToColor:dnSendButtonTintAbnormalColor] forState:UIControlStateDisabled];
66 | _sendButton.titleLabel.font = [UIFont systemFontOfSize:15.0f];
67 | _sendButton.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
68 | _sendButton.backgroundColor = [UIColor clearColor];
69 | [self addSubview:_sendButton];
70 | }
71 |
72 | - (void)setBadgeValue:(NSString *)badgeValue
73 | {
74 | CGRect rect = [badgeValue boundingRectWithSize:CGSizeMake(MAXFLOAT, 20) options:NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:kSendButtonFont} context:nil];
75 | self.badgeValueLabel.frame = CGRectMake(self.badgeValueLabel.left, self.badgeValueLabel.top, (rect.size.width + 9) > 20?(rect.size.width + 9):20, 20);
76 | self.backGroudView.width = self.badgeValueLabel.width;
77 | self.backGroudView.height = self.badgeValueLabel.height;
78 |
79 | self.sendButton.width = self.badgeValueLabel.width + kSendButtonTextWitdh;
80 | self.width = self.sendButton.width;
81 |
82 | self.badgeValueLabel.text = badgeValue;
83 |
84 | if (badgeValue.integerValue > 0) {
85 | [self showBadgeValue];
86 | self.backGroudView.transform =CGAffineTransformMakeScale(0, 0);
87 | [UIView animateWithDuration:0.2 animations:^{
88 | self.backGroudView.transform = CGAffineTransformMakeScale(1.1, 1.1);
89 | }
90 | completion:^(BOOL finished){
91 | [UIView animateWithDuration:0.1 animations:^{
92 | self.backGroudView.transform = CGAffineTransformMakeScale(1.0, 1.0);
93 | }];
94 | }];
95 |
96 | } else {
97 | [self hideBadgeValue];
98 | }
99 | }
100 |
101 | - (void)showBadgeValue
102 | {
103 | self.badgeValueLabel.hidden = NO;
104 | self.backGroudView.hidden = NO;
105 | }
106 |
107 | - (void)hideBadgeValue
108 | {
109 | self.badgeValueLabel.hidden = YES;
110 | self.backGroudView.hidden = YES;
111 | self.sendButton.adjustsImageWhenDisabled = YES;
112 | }
113 |
114 |
115 | - (void)addTaget:(id)target action:(SEL)action
116 | {
117 | [self.sendButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
118 | }
119 |
120 | @end
121 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImagePickerController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNImagePickerController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/10.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNImagePickerController.h"
10 | #import "DNAlbumTableViewController.h"
11 | #import "DNImageFlowViewController.h"
12 | #import "DNImagePickerHelper.h"
13 |
14 | NSString *kDNImagePickerStoredGroupKey = @"com.dennis.kDNImagePickerStoredGroup";
15 |
16 |
17 | @interface DNImagePickerController ()
18 |
19 | @property (nonatomic, weak) id navDelegate;
20 | @property (nonatomic, assign) BOOL isDuringPushAnimation;
21 |
22 | @end
23 |
24 | @implementation DNImagePickerController
25 |
26 | - (void)viewDidLoad {
27 | [super viewDidLoad];
28 |
29 | if (!self.delegate) {
30 | self.delegate = self;
31 | }
32 |
33 | self.interactivePopGestureRecognizer.delegate = self;
34 |
35 | NSString *propwetyID = [[NSUserDefaults standardUserDefaults] objectForKey:kDNImagePickerStoredGroupKey];
36 |
37 | if (propwetyID.length <= 0) {
38 | [self showAlbumList];
39 | } else {
40 | [self showImageFlow];
41 | }
42 | }
43 |
44 |
45 | - (void)didReceiveMemoryWarning {
46 | [super didReceiveMemoryWarning];
47 | // Dispose of any resources that can be recreated.
48 | }
49 | #pragma mark - priviate methods
50 | - (void)showAlbumList {
51 | DNAlbumTableViewController *albumTableViewController = [[DNAlbumTableViewController alloc] init];
52 | [self setViewControllers:@[albumTableViewController]];
53 | }
54 |
55 | - (void)showImageFlow {
56 | NSString *albumIdentifier = [DNImagePickerHelper albumIdentifier];
57 | DNAlbumTableViewController *albumTableViewController = [[DNAlbumTableViewController alloc] init];
58 | DNImageFlowViewController *imageFlowController = [[DNImageFlowViewController alloc] initWithAlbumIdentifier:albumIdentifier];
59 | [self setViewControllers:@[albumTableViewController,imageFlowController]];
60 | }
61 |
62 | - (void)chargeAuthorizationStatus:(DNAlbumAuthorizationStatus)status {
63 | if (!self.viewControllers.firstObject) {
64 | [self showAlbumList];
65 | }
66 |
67 | DNAlbumTableViewController *albumTableViewController = self.viewControllers.firstObject;
68 |
69 | switch (status) {
70 | case DNAlbumAuthorizationStatusAuthorized:
71 | // TODO:Authorized
72 | break;
73 | case DNAlbumAuthorizationStatusDenied:
74 | case DNAlbumAuthorizationStatusRestricted:
75 | [albumTableViewController showUnAuthorizedTipsView];
76 | break;
77 | case DNAlbumAuthorizationStatusNotDetermined:
78 | // TODO: requestAuthorization
79 | break;
80 |
81 | default:
82 | break;
83 | }
84 | }
85 |
86 | #pragma mark - UINavigationController
87 |
88 | - (void)setDelegate:(id)delegate
89 | {
90 | [super setDelegate:delegate ? self : nil];
91 | self.navDelegate = delegate != self ? delegate : nil;
92 | }
93 |
94 | - (void)pushViewController:(UIViewController *)viewController
95 | animated:(BOOL)animated __attribute__((objc_requires_super))
96 | {
97 | self.isDuringPushAnimation = YES;
98 | [super pushViewController:viewController animated:animated];
99 | }
100 |
101 | #pragma mark UINavigationControllerDelegate
102 |
103 | - (void)navigationController:(UINavigationController *)navigationController
104 | didShowViewController:(UIViewController *)viewController
105 | animated:(BOOL)animated
106 | {
107 | self.isDuringPushAnimation = NO;
108 | if ([self.navDelegate respondsToSelector:_cmd]) {
109 | [self.navDelegate navigationController:navigationController didShowViewController:viewController animated:animated];
110 | }
111 | }
112 |
113 | #pragma mark - UIGestureRecognizerDelegate
114 |
115 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
116 | {
117 | if (gestureRecognizer == self.interactivePopGestureRecognizer) {
118 | return [self.viewControllers count] > 1 && !self.isDuringPushAnimation;
119 | } else {
120 | return YES;
121 | }
122 | }
123 |
124 | #pragma mark - Delegate Forwarder
125 |
126 | - (BOOL)respondsToSelector:(SEL)s {
127 | return [super respondsToSelector:s] || [self.navDelegate respondsToSelector:s];
128 | }
129 |
130 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)s {
131 | return [super methodSignatureForSelector:s] ?: [(id)self.navDelegate methodSignatureForSelector:s];
132 | }
133 |
134 | - (void)forwardInvocation:(NSInvocation *)invocation {
135 | id delegate = self.navDelegate;
136 | if ([delegate respondsToSelector:invocation.selector]) {
137 | [invocation invokeWithTarget:delegate];
138 | }
139 | }
140 |
141 | @end
142 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNFullImageButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNFullImageButton.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/3/2.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNFullImageButton.h"
10 | #import "UIView+DNImagePicker.h"
11 |
12 | #define kDNFullImageButtonFont [UIFont systemFontOfSize:13]
13 | static NSInteger const buttonPadding = 10;
14 | static NSInteger const buttonImageWidth = 16;
15 |
16 | @interface DNFullImageButton ()
17 | @property (nonatomic, strong) UIButton *fullImageButton;
18 | @property (nonatomic, strong) UILabel *imageSizeLabel;
19 | @property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
20 | @end
21 |
22 | @implementation DNFullImageButton
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame {
25 | self = [super initWithFrame:frame];
26 | if (self) {
27 | self.backgroundColor = [UIColor clearColor];
28 | self.height = 28;
29 | self.width = CGRectGetWidth([[UIScreen mainScreen] bounds])/2 -20;
30 | [self fullImageButton];
31 | [self imageSizeLabel];
32 | [self indicatorView];
33 | self.selected = NO;
34 | }
35 | return self;
36 | }
37 |
38 | - (void)addTarget:(id)target action:(SEL)action {
39 | [self.fullImageButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
40 | }
41 |
42 | - (UILabel *)imageSizeLabel {
43 | if (!_imageSizeLabel) {
44 | _imageSizeLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 4, CGRectGetWidth(self.frame)- 100, 20)];
45 | _imageSizeLabel.backgroundColor = [UIColor clearColor];
46 | _imageSizeLabel.font = [UIFont systemFontOfSize:14.0f];
47 | _imageSizeLabel.textAlignment = NSTextAlignmentLeft;
48 | _imageSizeLabel.textColor = [UIColor whiteColor];
49 | [self addSubview:_imageSizeLabel];
50 | }
51 | return _imageSizeLabel;
52 | }
53 |
54 | - (UIButton *)fullImageButton {
55 | if (!_fullImageButton) {
56 | _fullImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
57 | _fullImageButton.width = [self fullImageButtonWidth];
58 | _fullImageButton.height = 28;
59 | _fullImageButton.backgroundColor = [UIColor clearColor];
60 | [_fullImageButton setTitle:NSLocalizedStringFromTable(@"fullImage", @"DNImagePicker", @"原图") forState:UIControlStateNormal];
61 | _fullImageButton.titleLabel.font = kDNFullImageButtonFont;
62 | [_fullImageButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
63 | [_fullImageButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
64 | [_fullImageButton setImage:[UIImage imageNamed:@"photo_full_image_unselected"] forState:UIControlStateNormal];
65 | [_fullImageButton setImage:[UIImage imageNamed:@"photo_full_image_selected"] forState:UIControlStateSelected];
66 | _fullImageButton.contentVerticalAlignment = NSTextAlignmentRight;
67 | [_fullImageButton setTitleEdgeInsets:UIEdgeInsetsMake(0, buttonPadding-buttonImageWidth, 6, 0)];
68 | [_fullImageButton setImageEdgeInsets:UIEdgeInsetsMake(6, 0, 6, _fullImageButton.width - buttonImageWidth)];
69 | [self addSubview:_fullImageButton];
70 | }
71 | return _fullImageButton;
72 | }
73 |
74 | - (UIActivityIndicatorView *)indicatorView {
75 | if (!_indicatorView) {
76 | _indicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(self.fullImageButton.width, 2, 26, 26)];
77 | _indicatorView.hidesWhenStopped = YES;
78 | [_indicatorView stopAnimating];
79 | [self addSubview:_indicatorView];
80 | }
81 | return _indicatorView;
82 | }
83 |
84 | - (CGFloat)fullImageButtonWidth {
85 | NSString *string = NSLocalizedStringFromTable(@"fullImage", @"DNImagePicker", @"原图");
86 | CGRect rect = [string boundingRectWithSize:CGSizeMake(MAXFLOAT, 20) options:NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:kDNFullImageButtonFont} context:nil];
87 | CGFloat width = buttonImageWidth + buttonPadding + CGRectGetWidth(rect);
88 | return width;
89 | }
90 |
91 | - (void)setSelected:(BOOL)selected {
92 | if (_selected != selected) {
93 | _selected = selected;
94 | self.fullImageButton.selected = _selected;
95 | self.fullImageButton.width = [self fullImageButtonWidth];
96 | [self.fullImageButton setTitleEdgeInsets:UIEdgeInsetsMake(0, buttonPadding-buttonImageWidth, 6, 0)];
97 | [self.fullImageButton setImageEdgeInsets:UIEdgeInsetsMake(6, 0, 6, self.fullImageButton.width - buttonImageWidth)];
98 | CGFloat labelWidth = self.width - self.fullImageButton.width;
99 | self.imageSizeLabel.left = self.fullImageButton.width;
100 | self.imageSizeLabel.width = labelWidth;
101 | self.imageSizeLabel.hidden = !_selected;
102 | }
103 | }
104 |
105 | - (void)setText:(NSString *)text {
106 | self.imageSizeLabel.text = text;
107 | }
108 |
109 | - (void)shouldAnimating:(BOOL)animate {
110 | if (self.selected) {
111 | self.imageSizeLabel.hidden = animate;
112 | if (animate) {
113 | [self.indicatorView startAnimating];
114 | } else {
115 | [self.indicatorView stopAnimating];
116 | }
117 | }
118 | }
119 | @end
120 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNBrowserCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNBrowserCell.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/28.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNBrowserCell.h"
10 | #import "DNTapDetectingImageView.h"
11 | #import "DNPhotoBrowser.h"
12 | #import "UIView+DNImagePicker.h"
13 | #import "DNAsset.h"
14 | #import "DNImagePickerHelper.h"
15 |
16 | @interface DNBrowserCell ()
17 | @property (nonatomic, strong) UIScrollView *zoomingScrollView;
18 | @property (nonatomic, strong) DNTapDetectingImageView *photoImageView;
19 |
20 | @end
21 |
22 | @implementation DNBrowserCell
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame
25 | {
26 | self = [super initWithFrame:frame];
27 | if (self) {
28 | [self zoomingScrollView];
29 | [self photoImageView];
30 | }
31 | return self;
32 | }
33 |
34 | - (void)prepareForReuse {
35 | [super prepareForReuse];
36 | self.photoImageView.image = nil;
37 | [self.photoImageView removeFromSuperview];
38 | [self.zoomingScrollView removeFromSuperview];
39 | self.zoomingScrollView = nil;
40 | self.photoImageView = nil;
41 | self.photoBrowser = nil;
42 | self.asset = nil;
43 | }
44 |
45 | #pragma mark - set
46 | - (void)setAsset:(DNAsset *)asset {
47 | if (_asset != asset) {
48 | _asset = asset;
49 | [self displayImage];
50 | }
51 | }
52 |
53 | // Get and display image
54 | - (void)displayImage {
55 | self.zoomingScrollView.maximumZoomScale = 1;
56 | self.zoomingScrollView.minimumZoomScale = 1;
57 | self.zoomingScrollView.zoomScale = 1;
58 | self.zoomingScrollView.contentSize = CGSizeMake(0, 0);
59 | __weak typeof(self)weakSelf = self;
60 | [DNImagePickerHelper fetchImageWithAsset:self.asset targetSize:self.zoomingScrollView.size needHighQuality:YES imageResutHandler:^(UIImage * _Nonnull image) {
61 | if (!image) {
62 | return;
63 | }
64 | __strong __typeof(weakSelf) strongSelf = weakSelf;
65 | strongSelf.photoImageView.image = image;
66 | strongSelf.photoImageView.hidden = NO;
67 | CGRect photoImageViewFrame;
68 | photoImageViewFrame.origin = CGPointZero;
69 | photoImageViewFrame.size = image.size;
70 | strongSelf.photoImageView.frame = photoImageViewFrame;
71 | strongSelf.zoomingScrollView.contentSize = photoImageViewFrame.size;
72 |
73 | // Set zoom to minimum zoom
74 | [strongSelf setMaxMinZoomScalesForCurrentBounds];
75 | [strongSelf setNeedsLayout];
76 | }];
77 | }
78 |
79 |
80 | #pragma mark - get
81 | - (DNTapDetectingImageView *)photoImageView
82 | {
83 | if (!_photoImageView) {
84 | _photoImageView = [[DNTapDetectingImageView alloc] initWithFrame:CGRectZero];
85 | _photoImageView.tapDelegate = self;
86 | _photoImageView.contentMode = UIViewContentModeCenter;
87 | _photoImageView.backgroundColor = [UIColor blackColor];
88 | [self.zoomingScrollView addSubview:_photoImageView];
89 | }
90 | return _photoImageView;
91 | }
92 |
93 | - (UIScrollView *)zoomingScrollView
94 | {
95 | if (!_zoomingScrollView) {
96 | _zoomingScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 0, self.frame.size.width-20, self.frame.size.height)];
97 | _zoomingScrollView.delegate = self;
98 | _zoomingScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth;
99 | _zoomingScrollView.showsHorizontalScrollIndicator = NO;
100 | _zoomingScrollView.showsVerticalScrollIndicator = NO;
101 | _zoomingScrollView.decelerationRate = UIScrollViewDecelerationRateFast;
102 | [self addSubview:_zoomingScrollView];
103 | }
104 | return _zoomingScrollView;
105 | }
106 |
107 | #pragma mark - Setup
108 | - (CGFloat)initialZoomScaleWithMinScale {
109 | CGFloat zoomScale = self.zoomingScrollView.minimumZoomScale;
110 | // Zoom image to fill if the aspect ratios are fairly similar
111 | CGSize boundsSize = self.zoomingScrollView.bounds.size;
112 | CGSize imageSize = self.photoImageView.image.size;
113 | CGFloat boundsAR = boundsSize.width / boundsSize.height;
114 | CGFloat imageAR = imageSize.width / imageSize.height;
115 | CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise
116 | CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise
117 | // Zooms standard portrait images on a 3.5in screen but not on a 4in screen.
118 | if (ABS(boundsAR - imageAR) < 0.17) {
119 | zoomScale = MAX(xScale, yScale);
120 | // Ensure we don't zoom in or out too far, just in case
121 | zoomScale = MIN(MAX(self.zoomingScrollView.minimumZoomScale, zoomScale), self.zoomingScrollView.maximumZoomScale);
122 | }
123 | return zoomScale;
124 | }
125 |
126 | - (void)setMaxMinZoomScalesForCurrentBounds {
127 | // Reset
128 | self.zoomingScrollView.maximumZoomScale = 1;
129 | self.zoomingScrollView.minimumZoomScale = 1;
130 | self.zoomingScrollView.zoomScale = 1;
131 |
132 | // Bail if no image
133 | if (!_photoImageView.image) return;
134 |
135 | // Reset position
136 | _photoImageView.frame = CGRectMake(0, 0, _photoImageView.frame.size.width, _photoImageView.frame.size.height);
137 |
138 | // Sizes
139 | CGSize boundsSize = self.zoomingScrollView.bounds.size;
140 | CGSize imageSize = _photoImageView.image.size;
141 |
142 | // Calculate Min
143 | CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise
144 | CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise
145 | CGFloat minScale = MIN(xScale, yScale); // use minimum of these to allow the image to become fully visible
146 |
147 | // Calculate Max
148 | CGFloat maxScale = 1.5;
149 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
150 | // Let them go a bit bigger on a bigger screen!
151 | maxScale = 4;
152 | }
153 |
154 | // Image is smaller than screen so no zooming!
155 | if (xScale >= 1 && yScale >= 1) {
156 | minScale = 1.0;
157 | }
158 |
159 | // Set min/max zoom
160 | self.zoomingScrollView.maximumZoomScale = maxScale;
161 | self.zoomingScrollView.minimumZoomScale = minScale;
162 |
163 | // Initial zoom
164 | self.zoomingScrollView.zoomScale = [self initialZoomScaleWithMinScale];
165 |
166 | // If we're zooming to fill then centralise
167 | if (self.zoomingScrollView.zoomScale != minScale) {
168 | // Centralise
169 | self.zoomingScrollView.contentOffset = CGPointMake((imageSize.width * self.zoomingScrollView.zoomScale - boundsSize.width) / 2.0,
170 | (imageSize.height * self.zoomingScrollView.zoomScale - boundsSize.height) / 2.0);
171 | // Disable scrolling initially until the first pinch to fix issues with swiping on an initally zoomed in photo
172 | self.zoomingScrollView.scrollEnabled = NO;
173 | }
174 |
175 | // Layout
176 | [self setNeedsLayout];
177 |
178 | }
179 |
180 | #pragma mark - Layout
181 |
182 | - (void)layoutSubviews {
183 | // Super
184 | [super layoutSubviews];
185 |
186 | // Center the image as it becomes smaller than the size of the screen
187 | CGSize boundsSize = self.zoomingScrollView.bounds.size;
188 | CGRect frameToCenter = _photoImageView.frame;
189 |
190 | // Horizontally
191 | if (frameToCenter.size.width < boundsSize.width) {
192 | frameToCenter.origin.x = floorf((boundsSize.width - frameToCenter.size.width) / 2.0);
193 | } else {
194 | frameToCenter.origin.x = 0;
195 | }
196 |
197 | // Vertically
198 | if (frameToCenter.size.height < boundsSize.height) {
199 | frameToCenter.origin.y = floorf((boundsSize.height - frameToCenter.size.height) / 2.0);
200 | } else {
201 | frameToCenter.origin.y = 0;
202 | }
203 |
204 | // Center
205 | if (!CGRectEqualToRect(_photoImageView.frame, frameToCenter))
206 | _photoImageView.frame = frameToCenter;
207 |
208 | }
209 |
210 | #pragma mark - UIScrollViewDelegate
211 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
212 | return self.photoImageView;
213 | }
214 |
215 | - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
216 | self.zoomingScrollView.scrollEnabled = YES; // reset
217 | }
218 |
219 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
220 | [self setNeedsLayout];
221 | [self layoutIfNeeded];
222 | }
223 |
224 | #pragma mark - Tap Detection
225 | - (void)handleSingleTap:(CGPoint)touchPoint {
226 | [self.photoBrowser performSelector:@selector(toggleControls) withObject:nil afterDelay:0.2];
227 | }
228 |
229 | - (void)handleDoubleTap:(CGPoint)touchPoint {
230 |
231 | // Cancel any single tap handling
232 | [NSObject cancelPreviousPerformRequestsWithTarget:self.photoBrowser];
233 | // Zoom
234 | if (self.zoomingScrollView.zoomScale != self.zoomingScrollView.minimumZoomScale && self.zoomingScrollView.zoomScale != [self initialZoomScaleWithMinScale]) {
235 |
236 | // Zoom out
237 | [self.zoomingScrollView setZoomScale:self.zoomingScrollView.minimumZoomScale animated:YES];
238 |
239 | } else {
240 |
241 | // Zoom in to twice the size
242 | CGFloat newZoomScale = ((self.zoomingScrollView.maximumZoomScale + self.zoomingScrollView.minimumZoomScale) / 2);
243 | CGFloat xsize = self.zoomingScrollView.bounds.size.width / newZoomScale;
244 | CGFloat ysize = self.zoomingScrollView.bounds.size.height / newZoomScale;
245 | [self.zoomingScrollView zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES];
246 |
247 | }
248 | }
249 |
250 | // Image View
251 | - (void)imageView:(UIImageView *)imageView singleTapDetected:(UITouch *)touch {
252 | [self handleSingleTap:[touch locationInView:imageView]];
253 | }
254 | - (void)imageView:(UIImageView *)imageView doubleTapDetected:(UITouch *)touch {
255 | [self handleDoubleTap:[touch locationInView:imageView]];
256 | }
257 |
258 | @end
259 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Views/DNAssetsViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNAssetsViewCell.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNAssetsViewCell.h"
10 | #import "DNImagePicker.h"
11 |
12 | @interface DNAssetsViewCell ()
13 | @property (nonatomic, strong, nonnull) UIImageView *imageView;
14 | @property (nonatomic, strong, nonnull) UIButton *checkButton;
15 | @property (nonatomic, strong, nonnull) UIImageView *checkImageView;
16 |
17 | @end
18 |
19 | @implementation DNAssetsViewCell
20 |
21 | - (instancetype)initWithFrame:(CGRect)frame {
22 | self = [super initWithFrame:frame];
23 | if (self) {
24 | [self setTranslatesAutoresizingMaskIntoConstraints:NO];
25 | [self imageView];
26 | [self checkButton];
27 | [self checkImageView];
28 | [self addContentConstraint];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)addContentConstraint {
34 | NSLayoutConstraint *imageConstraintsBottom = [NSLayoutConstraint
35 | constraintWithItem:self.imageView
36 | attribute:NSLayoutAttributeBottom
37 | relatedBy:NSLayoutRelationEqual
38 | toItem:self.contentView
39 | attribute:NSLayoutAttributeBottom
40 | multiplier:1.0f
41 | constant:0];
42 |
43 | NSLayoutConstraint *imageConstraintsleading = [NSLayoutConstraint
44 | constraintWithItem:self.imageView
45 | attribute:NSLayoutAttributeLeading
46 | relatedBy:NSLayoutRelationEqual
47 | toItem:self.contentView
48 | attribute:NSLayoutAttributeLeading
49 | multiplier:1.0
50 | constant:0];
51 |
52 | NSLayoutConstraint *imageContraintsTop = [NSLayoutConstraint
53 | constraintWithItem:self.imageView
54 | attribute:NSLayoutAttributeTop
55 | relatedBy:NSLayoutRelationEqual
56 | toItem:self.contentView
57 | attribute:NSLayoutAttributeTop
58 | multiplier:1.0
59 | constant:0];
60 |
61 | NSLayoutConstraint *imageViewConstraintTrailing = [NSLayoutConstraint
62 | constraintWithItem:self.imageView
63 | attribute:NSLayoutAttributeTrailing
64 | relatedBy:NSLayoutRelationEqual
65 | toItem:self.contentView
66 | attribute:NSLayoutAttributeTrailing
67 | multiplier:1.0
68 | constant:0];
69 |
70 | [self addConstraints:@[imageConstraintsBottom,imageConstraintsleading,imageContraintsTop,imageViewConstraintTrailing]];
71 |
72 | NSLayoutConstraint *checkConstraitRight = [NSLayoutConstraint
73 | constraintWithItem:self.checkButton
74 | attribute:NSLayoutAttributeTrailing
75 | relatedBy:NSLayoutRelationEqual
76 | toItem:self.contentView
77 | attribute:NSLayoutAttributeTrailing
78 | multiplier:1.0f
79 | constant:0];
80 |
81 | NSLayoutConstraint *checkConstraitTop = [NSLayoutConstraint
82 | constraintWithItem:self.checkButton
83 | attribute:NSLayoutAttributeTop
84 | relatedBy:NSLayoutRelationEqual
85 | toItem:self.contentView
86 | attribute:NSLayoutAttributeTop
87 | multiplier:1.0f
88 | constant:0];
89 |
90 | NSLayoutConstraint *chekBtViewConsraintWidth = [NSLayoutConstraint
91 | constraintWithItem:self.checkButton
92 | attribute:NSLayoutAttributeWidth
93 | relatedBy:NSLayoutRelationEqual
94 | toItem:self.imageView
95 | attribute:NSLayoutAttributeHeight
96 | multiplier:0.5f
97 | constant:0];
98 |
99 | NSLayoutConstraint *chekBtViewConsraintHeight = [NSLayoutConstraint
100 | constraintWithItem:self.checkButton
101 | attribute:NSLayoutAttributeHeight
102 | relatedBy:NSLayoutRelationEqual
103 | toItem:self.checkButton
104 | attribute:NSLayoutAttributeWidth
105 | multiplier:1.0
106 | constant:0];
107 |
108 | [self.contentView addConstraints:@[checkConstraitRight,checkConstraitTop,chekBtViewConsraintWidth,chekBtViewConsraintHeight]];
109 |
110 | NSDictionary *checkImageViewMetric = @{@"sideLength":@25};
111 | NSString *checkImageViewVFLH = @"H:[_checkImageView(sideLength)]-3-|";
112 | NSString *checkImageVIewVFLV = @"V:|-3-[_checkImageView(sideLength)]";
113 | NSArray *checkImageConstraintsH = [NSLayoutConstraint constraintsWithVisualFormat:checkImageViewVFLH options:0 metrics:checkImageViewMetric views:NSDictionaryOfVariableBindings(_checkImageView)];
114 | NSArray *checkImageConstraintsV = [NSLayoutConstraint constraintsWithVisualFormat:checkImageVIewVFLV options:0 metrics:checkImageViewMetric views:NSDictionaryOfVariableBindings(_checkImageView)];
115 |
116 | [self.contentView addConstraints:checkImageConstraintsH];
117 | [self.contentView addConstraints:checkImageConstraintsV];
118 | }
119 |
120 |
121 | - (void)fillWithAsset:(nonnull DNAsset *)asset isSelected:(BOOL)seleted {
122 | self.isSelected = seleted;
123 | if (self.asset) {
124 | [DNImagePickerHelper cancelFetchWithAssets:self.asset];
125 | }
126 | self.asset = asset;
127 |
128 | if (self.asset.cacheImage) {
129 | self.imageView.image = self.asset.cacheImage;
130 | return;
131 | }
132 |
133 | __weak typeof(self) wSelf = self;
134 | CGFloat kThumbSizeLength = ceil(([[UIScreen mainScreen] bounds].size.width -10)/4);
135 | [DNImagePickerHelper fetchImageWithAsset:self.asset
136 | targetSize:CGSizeMake(kThumbSizeLength, kThumbSizeLength)
137 | imageResutHandler:^(UIImage * _Nonnull image) {
138 | __strong typeof(wSelf) sSelf = wSelf;
139 | if (image) {
140 | sSelf.asset.cacheImage = image;
141 | sSelf.imageView.image = image;
142 | } else {
143 | sSelf.imageView.image = [UIImage imageNamed:@"assets_placeholder_picture"];
144 | }
145 | }];
146 | }
147 |
148 | - (void)setIsSelected:(BOOL)isSelected {
149 | _isSelected = isSelected;
150 | self.checkButton.selected = _isSelected;
151 | [self updateCheckImageView];
152 | }
153 |
154 | - (void)updateCheckImageView {
155 | if (self.checkButton.selected) {
156 | self.checkImageView.image = [UIImage imageNamed:@"photo_check_selected"];
157 |
158 | [UIView animateWithDuration:0.2 animations:^{
159 | self.checkImageView.transform = CGAffineTransformMakeScale(1.2, 1.2);
160 | }
161 | completion:^(BOOL finished){
162 | [UIView animateWithDuration:0.2 animations:^{
163 | self.checkImageView.transform = CGAffineTransformMakeScale(1.0, 1.0);
164 | }];
165 | }];
166 | } else {
167 | self.checkImageView.image = [UIImage imageNamed:@"photo_check_default"];
168 | }
169 | }
170 |
171 | - (void)checkButtonAction:(id)sender {
172 | if (self.checkButton.selected) {
173 | if (self.delegate && [self.delegate respondsToSelector:@selector(didDeselectItemAssetsViewCell:)]) {
174 | [self.delegate didDeselectItemAssetsViewCell:self];
175 | }
176 | } else {
177 | if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectItemAssetsViewCell:)]) {
178 | [self.delegate didSelectItemAssetsViewCell:self];
179 | }
180 | }
181 | }
182 |
183 | - (void)prepareForReuse {
184 | _isSelected = NO;
185 | _delegate = nil;
186 | }
187 |
188 | #pragma mark - Getter
189 | - (UIImageView *)imageView {
190 | if (!_imageView) {
191 | _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
192 | [_imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
193 | [self.contentView addSubview:_imageView];
194 | }
195 | return _imageView;
196 | }
197 |
198 | - (UIButton *)checkButton {
199 | if (!_checkButton) {
200 | _checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
201 |
202 | [_checkButton addTarget:self action:@selector(checkButtonAction:) forControlEvents:UIControlEventTouchUpInside];
203 | [_checkButton setTranslatesAutoresizingMaskIntoConstraints:NO];
204 | [self.contentView addSubview:_checkButton];
205 | }
206 | return _checkButton;
207 | }
208 |
209 | - (UIImageView *)checkImageView {
210 | if (!_checkImageView) {
211 | _checkImageView = [UIImageView new];
212 | _checkImageView.contentMode = UIViewContentModeScaleAspectFit;
213 | [_checkImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
214 | [self.contentView addSubview:_checkImageView];
215 | }
216 | return _checkImageView;
217 | }
218 |
219 | @end
220 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/DNImagePickerHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNImagePickerHelper.m
3 | // DNImagePicker
4 | //
5 | // Created by Ding Xiao on 16/8/23.
6 | // Copyright © 2016年 Dennis. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DNImagePickerHelper.h"
11 | #import "DNImageFetchOperation.h"
12 | #import "DNAlbum.h"
13 | #import "DNAsset.h"
14 |
15 | NSString * const DNImagePickerPhotoLibraryChangedNotification = @"DNImagePickerPhotoLibraryChangedNotification";
16 | static NSString* const kDNImagePickerStoredGroupKey = @"com.dennis.kDNImagePickerStoredGroup";
17 |
18 | static dispatch_queue_t imageFetchQueue() {
19 | static dispatch_queue_t queue = nil;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | queue = dispatch_queue_create("com.awesomedennis.dnimageFetchQueue", DISPATCH_QUEUE_SERIAL);
23 | });
24 | return queue;
25 | }
26 |
27 | @interface DNImagePickerHelper ()
28 | @property (nonatomic, strong) NSOperationQueue *imageFetchQueue;
29 | @property (nonatomic, strong) NSMutableDictionary *fetchImageOperationDics;
30 | @end
31 |
32 | @implementation DNImagePickerHelper
33 |
34 | + (instancetype)sharedHelper {
35 | static dispatch_once_t once;
36 | static id instance;
37 | dispatch_once(&once, ^{
38 | instance = [self new];
39 | });
40 | return instance;
41 | }
42 |
43 | - (instancetype)init {
44 | self = [super init];
45 | if (self) {
46 | _imageFetchQueue = [NSOperationQueue new];
47 | _imageFetchQueue.maxConcurrentOperationCount = 8;
48 | _imageFetchQueue.name = @"com.awesomedennis.dnnimagefetchOperationQueue";
49 | _fetchImageOperationDics = [NSMutableDictionary dictionary];
50 | }
51 | return self;
52 | }
53 |
54 | #pragma mark -
55 | #pragma mark - PHPhotoLibraryChangeObserver
56 | - (void)photoLibraryDidChange:(PHChange *)changeInstance {
57 | dispatch_async(dispatch_get_main_queue(), ^{
58 | [[NSNotificationCenter defaultCenter] postNotificationName:DNImagePickerPhotoLibraryChangedNotification object:nil];
59 | });
60 | }
61 |
62 | #pragma mark -
63 | #pragma mark - public
64 |
65 | + (DNAlbumAuthorizationStatus)authorizationStatus {
66 | return (DNAlbumAuthorizationStatus)[PHPhotoLibrary authorizationStatus];
67 | }
68 |
69 | + (void)requestAlbumListWithCompleteHandler:(void (^)(NSArray *))completeHandelr {
70 | dispatch_block_t block = ^{
71 | NSMutableArray *albums = [NSMutableArray arrayWithArray:[self fetchAlbumsResults]];
72 | if (!albums) {
73 | completeHandelr(nil);
74 | return;
75 | }
76 |
77 | PHFetchOptions *userAlbumsOptions = [[PHFetchOptions alloc] init];
78 | userAlbumsOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %@",@(PHAssetMediaTypeImage)];
79 | userAlbumsOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
80 |
81 | NSMutableArray *list = [NSMutableArray array];
82 | for (PHFetchResult *result in albums) {
83 | [result enumerateObjectsUsingBlock:^(PHAssetCollection *obj, NSUInteger idx, BOOL * _Nonnull stop) {
84 | PHFetchResult *assetResults = [PHAsset fetchAssetsInAssetCollection:obj options:userAlbumsOptions];
85 | NSInteger count = 0;
86 | switch (obj.assetCollectionType) {
87 | case PHAssetCollectionTypeAlbum:
88 | case PHAssetCollectionTypeSmartAlbum:
89 | count = assetResults.count;
90 | break;
91 | default:
92 | count = 0;
93 | break;
94 | }
95 |
96 | if (count > 0) {
97 | @autoreleasepool {
98 | DNAlbum *album = [DNAlbum albumWithAssetCollection:obj results:assetResults];
99 | [list addObject:album];
100 | }
101 | }
102 | }];
103 | }
104 | dispatch_async(dispatch_get_main_queue(), ^{
105 | if (completeHandelr) {
106 | completeHandelr([list copy]);
107 | }
108 | });
109 | };
110 | dispatch_async(imageFetchQueue(), block);
111 | }
112 |
113 | + (void)requestCurrentAblumWithCompleteHandler:(void (^)(DNAlbum *))completeHandler {
114 | void(^callBack)(DNAlbum *) = ^(DNAlbum * album){
115 | dispatch_async(dispatch_get_main_queue(), ^{
116 | completeHandler(album);
117 | });
118 | };
119 |
120 | dispatch_async(imageFetchQueue(), ^{
121 | DNAlbum *album = [[DNAlbum alloc] init];
122 | NSString *identifier = [DNImagePickerHelper albumIdentifier];
123 | if (!identifier || identifier.length <= 0) {
124 | callBack(album);
125 | return;
126 | }
127 |
128 | PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[identifier] options:nil];
129 |
130 | if (result.count <= 0) {
131 | callBack(album);
132 | return;
133 | }
134 |
135 | PHFetchOptions *options = [[PHFetchOptions alloc] init];
136 | options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %@",@(PHAssetMediaTypeImage)];
137 | options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
138 | PHAssetCollection *collection = result.firstObject;
139 |
140 | PHFetchResult *requestReslut = [PHAsset fetchAssetsInAssetCollection:collection options:options];
141 | album.albumTitle = collection.localizedTitle;
142 | album.results = requestReslut;
143 | album.count = requestReslut.count;
144 | album.identifier = collection.localIdentifier;
145 | callBack(album);
146 | });
147 | }
148 |
149 | + (void)fetchImageAssetsInAlbum:(DNAlbum *)album completeHandler:(void (^)(NSArray *))completeHandler {
150 | dispatch_async(imageFetchQueue(), ^{
151 | NSArray *array = [self fetchImageAssetsViaCollectionResults:album.results];
152 | dispatch_async(dispatch_get_main_queue(), ^{
153 | if (completeHandler) {
154 | completeHandler(array);
155 | }
156 | });
157 | });
158 | }
159 |
160 | + (void)fetchImageSizeWithAsset:(DNAsset *)asset
161 | imageSizeResultHandler:(void (^)(CGFloat imageSize, NSString * sizeString))handler {
162 | if (!asset.asset) {
163 | handler(0,@"0M");
164 | return;
165 | }
166 | [[PHImageManager defaultManager] requestImageDataForAsset:asset.asset
167 | options:nil
168 | resultHandler:^(NSData *imageData,
169 | NSString *dataUTI,
170 | UIImageOrientation orientation,
171 | NSDictionary *info) {
172 | NSString *string = @"0M";
173 | CGFloat imageSize = 0.0;
174 | if (!imageData) {
175 | handler(imageSize, string);
176 | return;
177 | }
178 | imageSize = imageData.length;
179 | if (imageSize > 1024*1024) {
180 | CGFloat size = imageSize/(1024*2024);
181 | string = [NSString stringWithFormat:@"%.1fM",size];
182 | } else {
183 | CGFloat size = imageSize/1024;
184 | string = [NSString stringWithFormat:@"%.1fK",size];
185 | }
186 | handler(imageSize, string);
187 | }];
188 | }
189 |
190 |
191 | + (void)fetchImageWithAsset:(DNAsset *)asset
192 | targetSize:(CGSize)targetSize
193 | imageResutHandler:(void (^)(UIImage *))handler {
194 | return [self fetchImageWithAsset:asset targetSize:targetSize needHighQuality:NO imageResutHandler:handler];
195 | }
196 |
197 | + (void)fetchImageWithAsset:(DNAsset *)asset
198 | targetSize:(CGSize)targetSize
199 | needHighQuality:(BOOL)isHighQuality
200 | imageResutHandler:(void (^)(UIImage *image))handler {
201 | if (!asset) {
202 | return;
203 | }
204 |
205 | DNImagePickerHelper *helper = [DNImagePickerHelper sharedHelper];
206 | DNImageFetchOperation *operation = [[DNImageFetchOperation alloc] initWithAsset:asset.asset];
207 | __weak typeof(helper) whelper = helper;
208 | [operation fetchImageWithTargetSize:targetSize needHighQuality:isHighQuality imageResutHandler:^(UIImage * _Nonnull image) {
209 | __strong typeof(whelper) shelper = whelper;
210 | [shelper.fetchImageOperationDics removeObjectForKey:asset.assetIdentifier];
211 | handler(image);
212 | }];
213 | [helper.imageFetchQueue addOperation:operation];
214 | [helper.fetchImageOperationDics setObject:operation forKey:asset.assetIdentifier];
215 | }
216 |
217 | + (void)cancelFetchWithAssets:(DNAsset *)asset {
218 | if (!asset) {
219 | return;
220 | }
221 | DNImagePickerHelper *helper = [DNImagePickerHelper sharedHelper];
222 | DNImageFetchOperation *operation = [helper.fetchImageOperationDics objectForKey:asset.assetIdentifier];
223 | if (operation) {
224 | [operation cancel];
225 | }
226 | [helper.fetchImageOperationDics removeObjectForKey:asset.assetIdentifier];
227 | }
228 |
229 | #pragma mark -
230 | #pragma mark - priviate
231 |
232 | /**
233 | * fetch `PHAsset` array via CollectionResults
234 | *
235 | * @param results collection fetch results
236 | *
237 | * @return `DNAsset` array in collection
238 | */
239 | + (NSArray *)fetchImageAssetsViaCollectionResults:(PHFetchResult *)results {
240 | NSMutableArray *array = [NSMutableArray arrayWithCapacity:results.count];
241 | if (!results) {
242 | return array;
243 | }
244 |
245 | [results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
246 | @autoreleasepool {
247 | DNAsset *asset = [DNAsset assetWithPHAsset:obj];
248 | [array addObject:asset];
249 | }
250 | }];
251 |
252 | return [array copy];
253 | }
254 |
255 | + (NSArray *)fetchAlbumsResults {
256 | PHFetchOptions *userAlbumsOptions = [[PHFetchOptions alloc] init];
257 | userAlbumsOptions.predicate = [NSPredicate predicateWithFormat:@"estimatedAssetCount > 0"];
258 | userAlbumsOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"startDate" ascending:YES]];
259 |
260 | NSMutableArray *albumsArray = [NSMutableArray array];
261 | [albumsArray addObject:
262 | [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum
263 | subtype:PHAssetCollectionSubtypeAlbumRegular
264 | options:nil]];
265 | [albumsArray addObject:
266 | [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
267 | subtype:PHAssetCollectionSubtypeAny
268 | options:userAlbumsOptions]];
269 | return albumsArray;
270 | }
271 |
272 | + (void)saveAblumIdentifier:(NSString *)identifier {
273 | if (identifier.length <= 0) return;
274 | [[NSUserDefaults standardUserDefaults] setObject:identifier forKey:kDNImagePickerStoredGroupKey];
275 | [[NSUserDefaults standardUserDefaults] synchronize];
276 | }
277 |
278 | + (NSString *)albumIdentifier {
279 | return [[NSUserDefaults standardUserDefaults] objectForKey:kDNImagePickerStoredGroupKey];
280 | }
281 |
282 | @end
283 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNImageFlowViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNImageFlowViewController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/11.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNImageFlowViewController.h"
10 | #import "DNImagePickerController.h"
11 | #import "DNPhotoBrowser.h"
12 | #import "UIViewController+DNImagePicker.h"
13 | #import "UIView+DNImagePicker.h"
14 | #import "UIColor+Hex.h"
15 | #import "DNAssetsViewCell.h"
16 | #import "DNSendButton.h"
17 | #import "DNImagePickerHelper.h"
18 | #import "DNAlbum.h"
19 | #import "DNAsset.h"
20 |
21 | static NSUInteger const kDNImageFlowMaxSeletedNumber = 9;
22 |
23 | @interface DNImageFlowViewController ()
24 |
25 | @property (nonatomic, strong) DNAlbum *album;
26 | @property (nonatomic, copy) NSString *albumIdentifier;
27 |
28 | @property (nonatomic, strong) UICollectionView *imageFlowCollectionView;
29 | @property (nonatomic, strong) DNSendButton *sendButton;
30 |
31 | @property (nonatomic, strong) NSMutableArray *assetsArray;
32 | @property (nonatomic, strong) NSMutableArray *selectedAssetsArray;
33 |
34 | @property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
35 |
36 | @property (nonatomic, assign) BOOL isFullImage;
37 | @end
38 |
39 | static NSString* const dnAssetsViewCellReuseIdentifier = @"DNAssetsViewCell";
40 |
41 | @implementation DNImageFlowViewController
42 |
43 | - (instancetype)initWithAlbumIdentifier:(NSString *)albumIdentifier {
44 | self = [super init];
45 | if (self) {
46 | _assetsArray = [NSMutableArray array];
47 | _selectedAssetsArray = [NSMutableArray array];
48 | _albumIdentifier = albumIdentifier;
49 | }
50 | return self;
51 | }
52 |
53 | - (instancetype)initWithAblum:(DNAlbum *)album {
54 | self = [super init];
55 | if (self) {
56 | _assetsArray = [NSMutableArray array];
57 | _selectedAssetsArray = [NSMutableArray array];
58 | _album = album;
59 |
60 | }
61 | return self;
62 | }
63 |
64 | - (void)viewDidLoad {
65 | [super viewDidLoad];
66 | [self setupView];
67 | [self setupData];
68 | }
69 |
70 | - (void)viewWillAppear:(BOOL)animated {
71 | [super viewWillAppear:animated];
72 | self.navigationController.toolbarHidden = NO;
73 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadData) name:DNImagePickerPhotoLibraryChangedNotification object:nil];
74 | }
75 |
76 | - (void)viewWillDisappear:(BOOL)animated {
77 | self.navigationController.toolbarHidden = YES;
78 | [[NSNotificationCenter defaultCenter] removeObserver:self];
79 | }
80 |
81 | - (void)setupData {
82 |
83 | if (!self.album && self.albumIdentifier.length > 0) {
84 | __weak typeof(self) wSelf = self;
85 | [DNImagePickerHelper requestCurrentAblumWithCompleteHandler:^(DNAlbum *album) {
86 | __strong typeof(wSelf) sSelf = wSelf;
87 | sSelf.album = album;
88 | sSelf.title = sSelf.album.albumTitle;
89 | [sSelf loadData];
90 | }];
91 | } else {
92 | self.title = self.album.albumTitle;
93 | [self loadData];
94 | }
95 | }
96 |
97 | - (void)setupView {
98 | self.view.backgroundColor = [UIColor whiteColor];
99 | [self createBarButtonItemAtPosition:DNImagePickerNavigationBarPositionLeft
100 | statusNormalImage:[UIImage imageNamed:@"back_normal"]
101 | statusHighlightImage:[UIImage imageNamed:@"back_highlight"]
102 | action:@selector(backButtonAction)];
103 | [self createBarButtonItemAtPosition:DNImagePickerNavigationBarPositionRight
104 | text:NSLocalizedStringFromTable(@"cancel", @"DNImagePicker", @"取消")
105 | action:@selector(cancelAction)];
106 |
107 | [self imageFlowCollectionView];
108 |
109 | UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedStringFromTable(@"preview", @"DNImagePicker", @"预览")
110 | style:UIBarButtonItemStylePlain
111 | target:self
112 | action:@selector(previewAction)];
113 | [item1 setTintColor:[UIColor blackColor]];
114 | item1.enabled = NO;
115 |
116 | UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
117 |
118 | UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:self.sendButton];
119 |
120 |
121 | UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
122 | item4.width = -10;
123 |
124 | [self setToolbarItems:@[item1,item2,item3,item4] animated:NO];
125 | }
126 |
127 | - (void)loadData {
128 | if (!self.assetsArray.count) {
129 | [self.indicatorView startAnimating];
130 | }
131 | __weak typeof(self) wSelf = self;
132 | [DNImagePickerHelper fetchImageAssetsInAlbum:self.album completeHandler:^(NSArray * imageArray) {
133 | __strong typeof(wSelf) sSelf = wSelf;
134 | [sSelf.indicatorView stopAnimating];
135 | [sSelf.assetsArray removeAllObjects];
136 | [sSelf.assetsArray addObjectsFromArray:imageArray];
137 | [self.imageFlowCollectionView reloadData];
138 | [self scrollerToBottom:NO];
139 | }];
140 | }
141 |
142 | #pragma mark - helpmethods
143 | - (void)scrollerToBottom:(BOOL)animated {
144 | NSInteger rows = [self.imageFlowCollectionView numberOfItemsInSection:0] - 1;
145 | [self.imageFlowCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:rows inSection:0]
146 | atScrollPosition:UICollectionViewScrollPositionBottom
147 | animated:animated];
148 | }
149 |
150 | - (DNImagePickerController *)dnImagePickerController {
151 | if (!self.navigationController
152 | ||
153 | ![self.navigationController isKindOfClass:[DNImagePickerController class]])
154 | {
155 | NSAssert(false, @"check the navigation controller");
156 | }
157 | return (DNImagePickerController *)self.navigationController;
158 | }
159 |
160 | - (void)removeAssetsObject:(DNAsset *)asset {
161 | if ([self.selectedAssetsArray containsObject:asset]) {
162 | [self.selectedAssetsArray removeObject:asset];
163 | }
164 | }
165 |
166 | - (void)addAssetsObject:(DNAsset *)asset {
167 | [self.selectedAssetsArray addObject:asset];
168 | }
169 |
170 | #pragma mark - priviate methods
171 | - (void)sendImages {
172 | [DNImagePickerHelper saveAblumIdentifier:self.album.identifier];
173 |
174 | DNImagePickerController *imagePicker = [self dnImagePickerController];
175 | if (imagePicker && [imagePicker.imagePickerDelegate respondsToSelector:@selector(dnImagePickerController:sendImages:isFullImage:)]) {
176 | [imagePicker.imagePickerDelegate dnImagePickerController:imagePicker
177 | sendImages:self.selectedAssetsArray
178 | isFullImage:self.isFullImage];
179 | }
180 | [self.navigationController dismissViewControllerAnimated:YES completion:nil];}
181 |
182 | - (void)browserPhotoAsstes:(NSArray *)assets pageIndex:(NSInteger)page {
183 | DNPhotoBrowser *browser = [[DNPhotoBrowser alloc] initWithPhotos:assets
184 | currentIndex:page
185 | fullImage:self.isFullImage];
186 | browser.delegate = self;
187 | browser.hidesBottomBarWhenPushed = YES;
188 | [self.navigationController pushViewController:browser animated:YES];
189 | }
190 |
191 | - (BOOL)seletedAssets:(DNAsset *)asset {
192 | if ([self.selectedAssetsArray containsObject:asset]) {
193 | return NO;
194 | }
195 | UIBarButtonItem *firstItem = self.toolbarItems.firstObject;
196 | firstItem.enabled = YES;
197 | if (self.selectedAssetsArray.count >= kDNImageFlowMaxSeletedNumber) {
198 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedStringFromTable(@"alertTitle", @"DNImagePicker", nil)
199 | message:NSLocalizedStringFromTable(@"alertContent", @"DNImagePicker", nil)
200 | delegate:self
201 | cancelButtonTitle:NSLocalizedStringFromTable(@"alertButton", @"DNImagePicker", nil)
202 | otherButtonTitles:nil, nil];
203 | [alert show];
204 | return NO;
205 | } else {
206 | [self addAssetsObject:asset];
207 | self.sendButton.badgeValue = [NSString stringWithFormat:@"%@",@(self.selectedAssetsArray.count)];
208 | return YES;
209 | }
210 | }
211 |
212 | - (void)deseletedAssets:(DNAsset *)asset {
213 | [self removeAssetsObject:asset];
214 | self.sendButton.badgeValue = [NSString stringWithFormat:@"%@",@(self.selectedAssetsArray.count)];
215 | if (self.selectedAssetsArray.count < 1) {
216 | UIBarButtonItem *firstItem = self.toolbarItems.firstObject;
217 | firstItem.enabled = NO;
218 | }
219 | }
220 |
221 | #pragma mark - getter/setter
222 |
223 | - (UICollectionView *)imageFlowCollectionView {
224 | if (!_imageFlowCollectionView) {
225 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
226 | layout.minimumLineSpacing = 2.0;
227 | layout.minimumInteritemSpacing = 2.0;
228 | layout.scrollDirection = UICollectionViewScrollDirectionVertical;
229 | _imageFlowCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) collectionViewLayout:layout];
230 | _imageFlowCollectionView.backgroundColor = [UIColor clearColor];
231 | [_imageFlowCollectionView registerClass:[DNAssetsViewCell class] forCellWithReuseIdentifier:dnAssetsViewCellReuseIdentifier];
232 | _imageFlowCollectionView.alwaysBounceVertical = YES;
233 | _imageFlowCollectionView.delegate = self;
234 | _imageFlowCollectionView.dataSource = self;
235 | _imageFlowCollectionView.showsHorizontalScrollIndicator = YES;
236 | [self.view addSubview:_imageFlowCollectionView];
237 | }
238 |
239 | return _imageFlowCollectionView;
240 | }
241 |
242 | - (DNSendButton *)sendButton {
243 | if (!_sendButton) {
244 | _sendButton = [[DNSendButton alloc] initWithFrame:CGRectZero];
245 | [_sendButton addTaget:self action:@selector(sendButtonAction:)];
246 | }
247 | return _sendButton;
248 | }
249 |
250 | - (UIActivityIndicatorView *)indicatorView {
251 | if (!_indicatorView) {
252 | _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
253 | _indicatorView.hidesWhenStopped = YES;
254 | _indicatorView.centerX = CGRectGetWidth(self.view.bounds)/2;
255 | _indicatorView.centerY = CGRectGetHeight(self.view.bounds)/2;
256 | [self.view addSubview:_indicatorView];
257 | }
258 | return _indicatorView;
259 | }
260 |
261 | #pragma mark - ui action
262 | - (void)backButtonAction {
263 | [self.navigationController popViewControllerAnimated:YES];
264 | }
265 |
266 | - (void)sendButtonAction:(id)sender {
267 | if (self.selectedAssetsArray.count > 0) {
268 | [self sendImages];
269 | }
270 | }
271 |
272 | - (void)previewAction {
273 | [self browserPhotoAsstes:self.selectedAssetsArray pageIndex:0];
274 | }
275 |
276 | - (void)cancelAction {
277 | DNImagePickerController *navController = [self dnImagePickerController];
278 | if (navController && [navController.imagePickerDelegate respondsToSelector:@selector(dnImagePickerControllerDidCancel:)]) {
279 | [navController.imagePickerDelegate dnImagePickerControllerDidCancel:navController];
280 | }
281 | }
282 |
283 | #pragma mark - DNAssetsViewCellDelegate
284 | - (void)didSelectItemAssetsViewCell:(DNAssetsViewCell *)assetsCell {
285 | assetsCell.isSelected = [self seletedAssets:assetsCell.asset];
286 | }
287 |
288 | - (void)didDeselectItemAssetsViewCell:(DNAssetsViewCell *)assetsCell {
289 | assetsCell.isSelected = NO;
290 | [self deseletedAssets:assetsCell.asset];
291 | }
292 |
293 | #pragma mark - UICollectionView delegate and Datasource
294 | - (NSInteger)collectionView:(UICollectionView *)collectionView
295 | numberOfItemsInSection:(NSInteger)section {
296 | return self.assetsArray.count;
297 | }
298 |
299 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
300 | cellForItemAtIndexPath:(NSIndexPath *)indexPath {
301 | DNAssetsViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:dnAssetsViewCellReuseIdentifier forIndexPath:indexPath];
302 | DNAsset *asset = self.assetsArray[indexPath.row];
303 | cell.delegate = self;
304 | [cell fillWithAsset:asset isSelected:[self.selectedAssetsArray containsObject:asset]];
305 |
306 | return cell;
307 | }
308 |
309 | - (void)collectionView:(UICollectionView *)collectionView
310 | didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
311 | [self browserPhotoAsstes:self.assetsArray pageIndex:indexPath.row];
312 | }
313 |
314 | #define kSizeThumbnailCollectionView ([UIScreen mainScreen].bounds.size.width-10)/4
315 | #pragma mark - UICollectionViewDelegateFlowLayout
316 | - (CGSize)collectionView:(UICollectionView *)collectionView
317 | layout:(UICollectionViewLayout *)collectionViewLayout
318 | sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
319 | CGSize size = CGSizeMake(kSizeThumbnailCollectionView, kSizeThumbnailCollectionView);
320 | return size;
321 | }
322 |
323 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
324 | layout:(UICollectionViewLayout*)collectionViewLayout
325 | insetForSectionAtIndex:(NSInteger)section {
326 | return UIEdgeInsetsMake(2, 2, 2, 2);
327 | }
328 |
329 | #pragma mark - DNPhotoBrowserDelegate
330 | - (void)sendImagesFromPhotobrowser:(DNPhotoBrowser *)photoBrowser currentAsset:(DNAsset *)asset {
331 | if (self.selectedAssetsArray.count <= 0) {
332 | [self seletedAssets:asset];
333 | [self.imageFlowCollectionView reloadData];
334 | }
335 | [self sendImages];
336 | }
337 |
338 | - (NSUInteger)seletedPhotosNumberInPhotoBrowser:(DNPhotoBrowser *)photoBrowser {
339 | return self.selectedAssetsArray.count;
340 | }
341 |
342 | - (BOOL)photoBrowser:(DNPhotoBrowser *)photoBrowser currentPhotoAssetIsSeleted:(DNAsset *)asset{
343 | return [self.selectedAssetsArray containsObject:asset];
344 | }
345 |
346 | - (BOOL)photoBrowser:(DNPhotoBrowser *)photoBrowser seletedAsset:(DNAsset *)asset {
347 | BOOL seleted = [self seletedAssets:asset];
348 | [self.imageFlowCollectionView reloadData];
349 | return seleted;
350 | }
351 |
352 | - (void)photoBrowser:(DNPhotoBrowser *)photoBrowser deseletedAsset:(DNAsset *)asset {
353 | [self deseletedAssets:asset];
354 | [self.imageFlowCollectionView reloadData];
355 | }
356 |
357 | - (void)photoBrowser:(DNPhotoBrowser *)photoBrowser seleteFullImage:(BOOL)fullImage {
358 | self.isFullImage = fullImage;
359 | }
360 |
361 | @end
362 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker/Classes/Controllers/DNPhotoBrowser.m:
--------------------------------------------------------------------------------
1 | //
2 | // DNPhotoBrowserViewController.m
3 | // ImagePicker
4 | //
5 | // Created by DingXiao on 15/2/28.
6 | // Copyright (c) 2015年 Dennis. All rights reserved.
7 | //
8 |
9 | #import "DNPhotoBrowser.h"
10 | #import "UIViewController+DNImagePicker.h"
11 | #import "UIView+DNImagePicker.h"
12 | #import "DNSendButton.h"
13 | #import "DNFullImageButton.h"
14 | #import "DNBrowserCell.h"
15 | #import "DNAsset.h"
16 | #import "DNImagePickerHelper.h"
17 |
18 | #pragma clang diagnostic push
19 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
20 |
21 |
22 | @interface DNPhotoBrowser ()
23 | {
24 | BOOL _statusBarShouldBeHidden;
25 | BOOL _didSavePreviousStateOfNavBar;
26 | BOOL _viewIsActive;
27 | BOOL _viewHasAppearedInitially;
28 | // Appearance
29 | BOOL _previousNavBarHidden;
30 | BOOL _previousNavBarTranslucent;
31 | UIBarStyle _previousNavBarStyle;
32 | UIColor *_previousNavBarTintColor;
33 | UIColor *_previousNavBarBarTintColor;
34 | UIBarButtonItem *_previousViewControllerBackButton;
35 | UIImage *_previousNavigationBarBackgroundImageDefault;
36 | UIImage *_previousNavigationBarBackgroundImageLandscapePhone;
37 | }
38 |
39 | @property (nonatomic, strong) UICollectionView *browserCollectionView;
40 | @property (nonatomic, strong) UIToolbar *toolbar;
41 | @property (nonatomic, strong) UIButton *checkButton;
42 | @property (nonatomic, strong) DNSendButton *sendButton;
43 | @property (nonatomic, strong) DNFullImageButton *fullImageButton;
44 |
45 | @property (nonatomic, strong) NSMutableArray *photoDataSources;
46 | @property (nonatomic, assign) NSInteger currentIndex;
47 |
48 | @property (nonatomic, getter=isFullImage) BOOL fullImage;
49 |
50 | @end
51 |
52 | @implementation DNPhotoBrowser
53 |
54 | - (instancetype)initWithPhotos:(NSArray *)photosArray
55 | currentIndex:(NSInteger)index
56 | fullImage:(BOOL)isFullImage {
57 | self = [super init];
58 | if (self) {
59 | _photoDataSources = [[NSMutableArray alloc] initWithArray:photosArray];
60 | _currentIndex = index;
61 | _fullImage = isFullImage;
62 | }
63 | return self;
64 | }
65 |
66 | - (void)viewDidLoad {
67 | [super viewDidLoad];
68 | [self setupView];
69 | [self updateSelestedNumber];
70 | [self updateNavigationBarAndToolBar];
71 | }
72 | - (void)viewWillAppear:(BOOL)animated {
73 |
74 | // Super
75 | [super viewWillAppear:animated];
76 |
77 | // Navigation bar appearance
78 | if (!_viewIsActive && [self.navigationController.viewControllers objectAtIndex:0] != self) {
79 | [self storePreviousNavBarAppearance];
80 | }
81 | [self setNavBarAppearance:animated];
82 |
83 | // Initial appearance
84 | if (!_viewHasAppearedInitially) {
85 | _viewHasAppearedInitially = YES;
86 | }
87 |
88 | //scroll to the current offset
89 | [self.browserCollectionView setContentOffset:CGPointMake(self.browserCollectionView.frame.size.width * self.currentIndex,0)];
90 | }
91 |
92 | - (void)viewWillDisappear:(BOOL)animated {
93 | // Check that we're being popped for good
94 | if ([self.navigationController.viewControllers objectAtIndex:0] != self &&
95 | ![self.navigationController.viewControllers containsObject:self]) {
96 |
97 | _viewIsActive = NO;
98 | [self restorePreviousNavBarAppearance:animated];
99 | }
100 |
101 | [self.navigationController.navigationBar.layer removeAllAnimations];
102 | [NSObject cancelPreviousPerformRequestsWithTarget:self];
103 | [self setControlsHidden:NO animated:NO];
104 |
105 | // Super
106 | [super viewWillDisappear:animated];
107 | }
108 |
109 | - (UIStatusBarStyle)preferredStatusBarStyle {
110 | return UIStatusBarStyleDefault;
111 | }
112 |
113 | - (void)viewDidAppear:(BOOL)animated {
114 | [super viewDidAppear:animated];
115 | _viewIsActive = YES;
116 | }
117 |
118 | - (void)viewDidDisappear:(BOOL)animated {
119 | _viewIsActive = NO;
120 | [super viewDidDisappear:animated];
121 | }
122 |
123 | #pragma mark - priviate
124 | - (void)setupView {
125 | self.automaticallyAdjustsScrollViewInsets = NO;
126 | self.view.clipsToBounds = YES;
127 | [self browserCollectionView];
128 | [self toolbar];
129 | [self setupBarButtonItems];
130 | [self createBarButtonItemAtPosition:DNImagePickerNavigationBarPositionLeft
131 | statusNormalImage:[UIImage imageNamed:@"back_normal"]
132 | statusHighlightImage:[UIImage imageNamed:@"back_highlight"]
133 | action:@selector(backButtonAction)];
134 | UIBarButtonItem *rightButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.checkButton];
135 | self.navigationItem.rightBarButtonItem = rightButtonItem;
136 | }
137 |
138 | - (void)setupData
139 | {
140 | self.photoDataSources = [NSMutableArray new];
141 | }
142 |
143 | - (void)setupBarButtonItems
144 | {
145 | UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithCustomView:self.fullImageButton];
146 | UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
147 | UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:self.sendButton];
148 | UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
149 | item4.width = -10;
150 |
151 | [self.toolbar setItems:@[item1,item2,item3,item4]];
152 | }
153 |
154 | - (void)updateNavigationBarAndToolBar {
155 | NSUInteger totalNumber = self.photoDataSources.count;
156 | self.title = [NSString stringWithFormat:@"%@/%@",@(self.currentIndex+1),@(totalNumber)];
157 | BOOL isSeleted = NO;
158 | if ([self.delegate respondsToSelector:@selector(photoBrowser:currentPhotoAssetIsSeleted:)]) {
159 | isSeleted = [self.delegate photoBrowser:self currentPhotoAssetIsSeleted:[self.photoDataSources objectAtIndex:self.currentIndex]];
160 | }
161 | self.checkButton.selected = isSeleted;
162 | self.fullImageButton.selected = self.isFullImage;
163 |
164 | if (self.isFullImage) {
165 | __weak typeof(self) wSelf = self;
166 | [DNImagePickerHelper fetchImageSizeWithAsset:self.photoDataSources[self.currentIndex] imageSizeResultHandler:^(CGFloat imageSize, NSString *sizeString) {
167 | __strong typeof(wSelf) sSelf = wSelf;
168 | sSelf.fullImageButton.text = sizeString;
169 | }];
170 | }
171 | }
172 |
173 | - (void)updateSelestedNumber
174 | {
175 | NSUInteger selectedNumber = 0;
176 | if ([self.delegate respondsToSelector:@selector(seletedPhotosNumberInPhotoBrowser:)]) {
177 | selectedNumber = [self.delegate seletedPhotosNumberInPhotoBrowser:self];
178 | }
179 | self.sendButton.badgeValue = [NSString stringWithFormat:@"%@",@(selectedNumber)];
180 | }
181 |
182 | #pragma mark - Nav Bar Appearance
183 | - (void)setNavBarAppearance:(BOOL)animated {
184 | [self.navigationController setNavigationBarHidden:NO animated:animated];
185 | UINavigationBar *navBar = self.navigationController.navigationBar;
186 | navBar.tintColor = [UIColor whiteColor];
187 | if ([navBar respondsToSelector:@selector(setBarTintColor:)]) {
188 | navBar.barTintColor = nil;
189 | navBar.shadowImage = nil;
190 | }
191 | navBar.translucent = YES;
192 | navBar.barStyle = UIBarStyleBlackTranslucent;
193 | if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
194 | [navBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
195 | [navBar setBackgroundImage:nil forBarMetrics:UIBarMetricsCompact];;
196 | }
197 | }
198 |
199 |
200 | - (void)storePreviousNavBarAppearance {
201 | _didSavePreviousStateOfNavBar = YES;
202 | if ([UINavigationBar instancesRespondToSelector:@selector(barTintColor)]) {
203 | _previousNavBarBarTintColor = self.navigationController.navigationBar.barTintColor;
204 | }
205 | _previousNavBarTranslucent = self.navigationController.navigationBar.translucent;
206 | _previousNavBarTintColor = self.navigationController.navigationBar.tintColor;
207 | _previousNavBarHidden = self.navigationController.navigationBarHidden;
208 | _previousNavBarStyle = self.navigationController.navigationBar.barStyle;
209 | if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
210 | _previousNavigationBarBackgroundImageDefault = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
211 | _previousNavigationBarBackgroundImageLandscapePhone = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsCompact];
212 | }
213 | }
214 |
215 | - (void)restorePreviousNavBarAppearance:(BOOL)animated {
216 | if (_didSavePreviousStateOfNavBar) {
217 | [self.navigationController setNavigationBarHidden:_previousNavBarHidden animated:animated];
218 | UINavigationBar *navBar = self.navigationController.navigationBar;
219 | navBar.tintColor = _previousNavBarTintColor;
220 | navBar.translucent = _previousNavBarTranslucent;
221 | if ([UINavigationBar instancesRespondToSelector:@selector(barTintColor)]) {
222 | navBar.barTintColor = _previousNavBarBarTintColor;
223 | }
224 | navBar.barStyle = _previousNavBarStyle;
225 | if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
226 | [navBar setBackgroundImage:_previousNavigationBarBackgroundImageDefault forBarMetrics:UIBarMetricsDefault];
227 | [navBar setBackgroundImage:_previousNavigationBarBackgroundImageLandscapePhone forBarMetrics:UIBarMetricsCompact];
228 | }
229 | // Restore back button if we need to
230 | if (_previousViewControllerBackButton) {
231 | UIViewController *previousViewController = [self.navigationController topViewController]; // We've disappeared so previous is now top
232 | previousViewController.navigationItem.backBarButtonItem = _previousViewControllerBackButton;
233 | _previousViewControllerBackButton = nil;
234 | }
235 | }
236 | }
237 |
238 | #pragma mark - ui actions
239 | - (void)checkButtonAction {
240 | if (self.checkButton.selected) {
241 | if (self.delegate && [self.delegate respondsToSelector:@selector(photoBrowser:deseletedAsset:)]) {
242 | [self.delegate photoBrowser:self deseletedAsset:self.photoDataSources[self.currentIndex]];
243 | self.checkButton.selected = NO;
244 | }
245 | } else {
246 | if (self.delegate && [self.delegate respondsToSelector:@selector(photoBrowser:seletedAsset:)]) {
247 | self.checkButton.selected = [self.delegate photoBrowser:self seletedAsset:self.photoDataSources[self.currentIndex]];
248 | }
249 | }
250 |
251 | [self updateSelestedNumber];
252 | }
253 |
254 | - (void)backButtonAction {
255 | [self.navigationController popViewControllerAnimated:YES];
256 | }
257 |
258 | - (void)sendButtonAction {
259 | if ([self.delegate respondsToSelector:@selector(sendImagesFromPhotobrowser:currentAsset:)]) {
260 | [self.delegate sendImagesFromPhotobrowser:self currentAsset:self.photoDataSources[self.currentIndex]];
261 | }
262 | }
263 |
264 | - (void)fullImageButtonAction {
265 | self.fullImageButton.selected = !self.fullImageButton.selected;
266 | self.fullImage = self.fullImageButton.selected;
267 | if ([self.delegate respondsToSelector:@selector(photoBrowser:seleteFullImage:)]) {
268 | [self.delegate photoBrowser:self seleteFullImage:self.isFullImage];
269 | }
270 | if (self.fullImageButton.selected) {
271 | [self updateNavigationBarAndToolBar];
272 | BOOL success = [self.delegate photoBrowser:self seletedAsset:self.photoDataSources[self.currentIndex]];
273 | if (success) {
274 | [self updateSelestedNumber];
275 | [self updateNavigationBarAndToolBar];
276 | }
277 | }
278 | }
279 |
280 | #pragma mark - get/set
281 | - (UIButton *)checkButton {
282 | if (!_checkButton) {
283 | _checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
284 | _checkButton.frame = CGRectMake(0, 0, 25, 25);
285 | [_checkButton setBackgroundImage:[UIImage imageNamed:@"photo_check_selected"] forState:UIControlStateSelected];
286 | [_checkButton setBackgroundImage:[UIImage imageNamed:@"photo_check_default"] forState:UIControlStateNormal];
287 | [_checkButton addTarget:self action:@selector(checkButtonAction) forControlEvents:UIControlEventTouchUpInside];
288 | }
289 | return _checkButton;
290 | }
291 |
292 | - (DNFullImageButton *)fullImageButton {
293 | if (!_fullImageButton) {
294 | _fullImageButton = [[DNFullImageButton alloc] initWithFrame:CGRectZero];
295 | [_fullImageButton addTarget:self action:@selector(fullImageButtonAction)];
296 | _fullImageButton.selected = self.isFullImage;
297 | }
298 | return _fullImageButton;
299 | }
300 |
301 | - (DNSendButton *)sendButton {
302 | if (!_sendButton) {
303 | _sendButton = [[DNSendButton alloc] initWithFrame:CGRectZero];
304 | [_sendButton addTaget:self action:@selector(sendButtonAction)];
305 | }
306 | return _sendButton;
307 | }
308 |
309 | - (UIToolbar *)toolbar {
310 | if (!_toolbar) {
311 | CGFloat height = 44;
312 | _toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height)];
313 | if ([[UIToolbar class] respondsToSelector:@selector(appearance)]) {
314 | [_toolbar setBackgroundImage:nil forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
315 | [_toolbar setBackgroundImage:nil forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsCompact];
316 | }
317 | _toolbar.barStyle = UIBarStyleBlackTranslucent;
318 | _toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
319 | [self.view addSubview:_toolbar];
320 | }
321 | return _toolbar;
322 | }
323 |
324 | - (UICollectionView *)browserCollectionView {
325 | if (!_browserCollectionView) {
326 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
327 | layout.minimumInteritemSpacing = 0;
328 | layout.minimumLineSpacing = 0;
329 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
330 |
331 | _browserCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(-10, 0, self.view.bounds.size.width+20, self.view.bounds.size.height+1) collectionViewLayout:layout];
332 | _browserCollectionView.backgroundColor = [UIColor blackColor];
333 | [_browserCollectionView registerClass:[DNBrowserCell class] forCellWithReuseIdentifier:NSStringFromClass([DNBrowserCell class])];
334 | _browserCollectionView.delegate = self;
335 | _browserCollectionView.dataSource = self;
336 | _browserCollectionView.pagingEnabled = YES;
337 | _browserCollectionView.showsHorizontalScrollIndicator = NO;
338 | _browserCollectionView.showsVerticalScrollIndicator = NO;
339 | [self.view addSubview:_browserCollectionView];
340 | }
341 | return _browserCollectionView;
342 | }
343 |
344 | #pragma mark - UICollectionViewDataSource
345 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
346 | return [self.photoDataSources count];
347 | }
348 |
349 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
350 | DNBrowserCell *cell = (DNBrowserCell *)[collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([DNBrowserCell class]) forIndexPath:indexPath];
351 | cell.asset = [self.photoDataSources objectAtIndex:indexPath.row];
352 | cell.photoBrowser = self;
353 | return cell;
354 | }
355 |
356 | #pragma mark - UICollectionViewDelegateFlowLayout
357 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
358 | return CGSizeMake(self.view.bounds.size.width+20, self.view.bounds.size.height);
359 | }
360 |
361 | #pragma mark - scrollerViewDelegate
362 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
363 | CGFloat offsetX = scrollView.contentOffset.x;
364 | CGFloat itemWidth = CGRectGetWidth(self.browserCollectionView.frame);
365 | CGFloat currentPageOffset = itemWidth * self.currentIndex;
366 | CGFloat deltaOffset = offsetX - currentPageOffset;
367 | if (fabs(deltaOffset) >= itemWidth/2 ) {
368 | [self.fullImageButton shouldAnimating:YES];
369 | } else {
370 | [self.fullImageButton shouldAnimating:NO];
371 | }
372 | }
373 |
374 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
375 | CGFloat offsetX = scrollView.contentOffset.x;
376 | CGFloat itemWidth = CGRectGetWidth(self.browserCollectionView.frame);
377 | if (offsetX >= 0){
378 | NSInteger page = offsetX / itemWidth;
379 | [self didScrollToPage:page];
380 | }
381 |
382 | [self.fullImageButton shouldAnimating:NO];
383 | }
384 |
385 | - (void)didScrollToPage:(NSInteger)page {
386 | self.currentIndex = page;
387 | [self updateNavigationBarAndToolBar];
388 | }
389 |
390 | #pragma mark - Control Hiding / Showing
391 | // Fades all controls slide and fade
392 | - (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated{
393 | // Force visible
394 | if (!self.photoDataSources || !self.photoDataSources.count)
395 | hidden = NO;
396 | // Animations & positions
397 | CGFloat animatonOffset = 20;
398 | CGFloat animationDuration = (animated ? 0.35 : 0);
399 |
400 | // Status bar
401 | if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
402 | // Hide status bar
403 | _statusBarShouldBeHidden = hidden;
404 | [UIView animateWithDuration:animationDuration animations:^(void) {
405 | [self setNeedsStatusBarAppearanceUpdate];
406 | } completion:^(BOOL finished) {}];
407 | }
408 |
409 | CGRect frame = CGRectIntegral(CGRectMake(0, self.view.bounds.size.height - 44, self.view.bounds.size.width, 44));
410 |
411 | // Pre-appear animation positions for iOS 7 sliding
412 | if ([self areControlsHidden] && !hidden && animated) {
413 | // Toolbar
414 | self.toolbar.frame = CGRectOffset(frame, 0, animatonOffset);
415 | }
416 |
417 | [UIView animateWithDuration:animationDuration animations:^(void) {
418 | CGFloat alpha = hidden ? 0 : 1;
419 | // Nav bar slides up on it's own on iOS 7
420 | [self.navigationController.navigationBar setAlpha:alpha];
421 | // Toolbar
422 | self.toolbar.frame = frame;
423 | if (hidden) self.toolbar.frame = CGRectOffset(self.toolbar.frame, 0, animatonOffset);
424 | self.toolbar.alpha = alpha;
425 |
426 | } completion:^(BOOL finished) {}];
427 | }
428 |
429 | - (BOOL)prefersStatusBarHidden {
430 | return _statusBarShouldBeHidden;
431 | }
432 |
433 | - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
434 | return UIStatusBarAnimationSlide;
435 | }
436 |
437 | - (BOOL)areControlsHidden { return (_toolbar.alpha == 0); }
438 | - (void)hideControls { [self setControlsHidden:YES animated:YES]; }
439 | - (void)toggleControls { [self setControlsHidden:![self areControlsHidden] animated:YES]; }
440 | @end
441 | #pragma clang diagnostic pop
442 |
--------------------------------------------------------------------------------
/DNImagePicker/DNImagePicker.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 24D077EA216F4BF2004E397A /* UIColor+Hex.m in Sources */ = {isa = PBXBuildFile; fileRef = 24D077E9216F4BF2004E397A /* UIColor+Hex.m */; };
11 | 24EBD7FA216CB58700B020FA /* DNImageFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 24EBD7F9216CB58700B020FA /* DNImageFetchOperation.m */; };
12 | 952600B21D2B9D4100080227 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600B11D2B9D4100080227 /* main.m */; };
13 | 952600B51D2B9D4100080227 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600B41D2B9D4100080227 /* AppDelegate.m */; };
14 | 952600B81D2B9D4100080227 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600B71D2B9D4100080227 /* ViewController.m */; };
15 | 952600BB1D2B9D4100080227 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 952600B91D2B9D4100080227 /* Main.storyboard */; };
16 | 952600BD1D2B9D4100080227 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 952600BC1D2B9D4100080227 /* Assets.xcassets */; };
17 | 952600C01D2B9D4100080227 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 952600BE1D2B9D4100080227 /* LaunchScreen.storyboard */; };
18 | 952600D41D2BA05700080227 /* DNImagePickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600CD1D2BA05700080227 /* DNImagePickerController.m */; };
19 | 952600D51D2BA05700080227 /* DNAlbumTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600CF1D2BA05700080227 /* DNAlbumTableViewController.m */; };
20 | 952600D61D2BA05700080227 /* DNImageFlowViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600D11D2BA05700080227 /* DNImageFlowViewController.m */; };
21 | 952600D71D2BA05700080227 /* DNPhotoBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600D31D2BA05700080227 /* DNPhotoBrowser.m */; };
22 | 952600EA1D2BA26400080227 /* DNBrowserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600DC1D2BA26400080227 /* DNBrowserCell.m */; };
23 | 952600EB1D2BA26400080227 /* DNTapDetectingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600DE1D2BA26400080227 /* DNTapDetectingImageView.m */; };
24 | 952600EC1D2BA26400080227 /* DNAssetsViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600E01D2BA26400080227 /* DNAssetsViewCell.m */; };
25 | 952600ED1D2BA26400080227 /* DNSendButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600E21D2BA26400080227 /* DNSendButton.m */; };
26 | 952600EE1D2BA26400080227 /* DNFullImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600E41D2BA26400080227 /* DNFullImageButton.m */; };
27 | 952600EF1D2BA26400080227 /* DNBadgeLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600E61D2BA26400080227 /* DNBadgeLabel.m */; };
28 | 952600F01D2BA26400080227 /* DNUnAuthorizedTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 952600E81D2BA26400080227 /* DNUnAuthorizedTipsView.m */; };
29 | 952600F21D2BA28000080227 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 952600F11D2BA28000080227 /* AssetsLibrary.framework */; };
30 | 952600F41D2BA29100080227 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 952600F31D2BA29100080227 /* Photos.framework */; };
31 | 952601031D2BAF6D00080227 /* imageResources.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 952601011D2BAF6D00080227 /* imageResources.xcassets */; };
32 | 952601051D2BAF7700080227 /* DNImagePicker.strings in Resources */ = {isa = PBXBuildFile; fileRef = 952601071D2BAF7700080227 /* DNImagePicker.strings */; };
33 | 952601111D2BB7F700080227 /* UIViewController+DNImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9526010A1D2BB7F700080227 /* UIViewController+DNImagePicker.m */; };
34 | 952601141D2BB7F700080227 /* UIView+DNImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 952601101D2BB7F700080227 /* UIView+DNImagePicker.m */; };
35 | 9526011C1D2BBB4A00080227 /* InfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952601171D2BBB4A00080227 /* InfoViewController.m */; };
36 | 9526011D1D2BBB4A00080227 /* CollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 952601191D2BBB4A00080227 /* CollectionViewController.m */; };
37 | 9526011E1D2BBB4A00080227 /* CollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9526011B1D2BBB4A00080227 /* CollectionViewCell.m */; };
38 | 952601211D2BBBA500080227 /* DNAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 952601201D2BBBA500080227 /* DNAsset.m */; };
39 | 9526012A1D2D112500080227 /* DNAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = 952601291D2D112500080227 /* DNAlbum.m */; };
40 | 95A147311D6C15A900E80455 /* DNImagePickerHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A147301D6C15A900E80455 /* DNImagePickerHelper.m */; };
41 | 95BE232A1D73490700EDBAF3 /* DNAlbumCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 95BE23291D73490700EDBAF3 /* DNAlbumCell.m */; };
42 | /* End PBXBuildFile section */
43 |
44 | /* Begin PBXFileReference section */
45 | 24D077E8216F4BF2004E397A /* UIColor+Hex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Hex.h"; sourceTree = ""; };
46 | 24D077E9216F4BF2004E397A /* UIColor+Hex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Hex.m"; sourceTree = ""; };
47 | 24EBD7F8216CB58700B020FA /* DNImageFetchOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DNImageFetchOperation.h; path = Controllers/DNImageFetchOperation.h; sourceTree = ""; };
48 | 24EBD7F9216CB58700B020FA /* DNImageFetchOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DNImageFetchOperation.m; path = Controllers/DNImageFetchOperation.m; sourceTree = ""; };
49 | 952600AD1D2B9D4100080227 /* DNImagePicker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DNImagePicker.app; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 952600B11D2B9D4100080227 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
51 | 952600B31D2B9D4100080227 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../DNImagePicker/AppDelegate.h; sourceTree = ""; };
52 | 952600B41D2B9D4100080227 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ../DNImagePicker/AppDelegate.m; sourceTree = ""; };
53 | 952600B61D2B9D4100080227 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = ../DNImagePicker/ViewController.h; sourceTree = ""; };
54 | 952600B71D2B9D4100080227 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ViewController.m; path = ../DNImagePicker/ViewController.m; sourceTree = ""; };
55 | 952600BA1D2B9D4100080227 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
56 | 952600BC1D2B9D4100080227 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../DNImagePicker/Assets.xcassets; sourceTree = ""; };
57 | 952600BF1D2B9D4100080227 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
58 | 952600C11D2B9D4100080227 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../DNImagePicker/Info.plist; sourceTree = ""; };
59 | 952600CC1D2BA05700080227 /* DNImagePickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNImagePickerController.h; sourceTree = ""; };
60 | 952600CD1D2BA05700080227 /* DNImagePickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNImagePickerController.m; sourceTree = ""; };
61 | 952600CE1D2BA05700080227 /* DNAlbumTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNAlbumTableViewController.h; sourceTree = ""; };
62 | 952600CF1D2BA05700080227 /* DNAlbumTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNAlbumTableViewController.m; sourceTree = ""; };
63 | 952600D01D2BA05700080227 /* DNImageFlowViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNImageFlowViewController.h; sourceTree = ""; };
64 | 952600D11D2BA05700080227 /* DNImageFlowViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNImageFlowViewController.m; sourceTree = ""; };
65 | 952600D21D2BA05700080227 /* DNPhotoBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNPhotoBrowser.h; sourceTree = ""; };
66 | 952600D31D2BA05700080227 /* DNPhotoBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNPhotoBrowser.m; sourceTree = ""; };
67 | 952600DB1D2BA26400080227 /* DNBrowserCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBrowserCell.h; sourceTree = ""; };
68 | 952600DC1D2BA26400080227 /* DNBrowserCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNBrowserCell.m; sourceTree = ""; };
69 | 952600DD1D2BA26400080227 /* DNTapDetectingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNTapDetectingImageView.h; sourceTree = ""; };
70 | 952600DE1D2BA26400080227 /* DNTapDetectingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNTapDetectingImageView.m; sourceTree = ""; };
71 | 952600DF1D2BA26400080227 /* DNAssetsViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNAssetsViewCell.h; sourceTree = ""; };
72 | 952600E01D2BA26400080227 /* DNAssetsViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNAssetsViewCell.m; sourceTree = ""; };
73 | 952600E11D2BA26400080227 /* DNSendButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSendButton.h; sourceTree = ""; };
74 | 952600E21D2BA26400080227 /* DNSendButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNSendButton.m; sourceTree = ""; };
75 | 952600E31D2BA26400080227 /* DNFullImageButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNFullImageButton.h; sourceTree = ""; };
76 | 952600E41D2BA26400080227 /* DNFullImageButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNFullImageButton.m; sourceTree = ""; };
77 | 952600E51D2BA26400080227 /* DNBadgeLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBadgeLabel.h; sourceTree = ""; };
78 | 952600E61D2BA26400080227 /* DNBadgeLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNBadgeLabel.m; sourceTree = ""; };
79 | 952600E71D2BA26400080227 /* DNUnAuthorizedTipsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNUnAuthorizedTipsView.h; sourceTree = ""; };
80 | 952600E81D2BA26400080227 /* DNUnAuthorizedTipsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNUnAuthorizedTipsView.m; sourceTree = ""; };
81 | 952600F11D2BA28000080227 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
82 | 952600F31D2BA29100080227 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; };
83 | 952601011D2BAF6D00080227 /* imageResources.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = imageResources.xcassets; sourceTree = ""; };
84 | 952601061D2BAF7700080227 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/DNImagePicker.strings; sourceTree = ""; };
85 | 952601081D2BAFB200080227 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/DNImagePicker.strings"; sourceTree = ""; };
86 | 952601091D2BB7F700080227 /* UIViewController+DNImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+DNImagePicker.h"; sourceTree = ""; };
87 | 9526010A1D2BB7F700080227 /* UIViewController+DNImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+DNImagePicker.m"; sourceTree = ""; };
88 | 9526010F1D2BB7F700080227 /* UIView+DNImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+DNImagePicker.h"; sourceTree = ""; };
89 | 952601101D2BB7F700080227 /* UIView+DNImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+DNImagePicker.m"; sourceTree = ""; };
90 | 952601161D2BBB4A00080227 /* InfoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoViewController.h; sourceTree = ""; };
91 | 952601171D2BBB4A00080227 /* InfoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InfoViewController.m; sourceTree = ""; };
92 | 952601181D2BBB4A00080227 /* CollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionViewController.h; sourceTree = ""; };
93 | 952601191D2BBB4A00080227 /* CollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionViewController.m; sourceTree = ""; };
94 | 9526011A1D2BBB4A00080227 /* CollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionViewCell.h; sourceTree = ""; };
95 | 9526011B1D2BBB4A00080227 /* CollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionViewCell.m; sourceTree = ""; };
96 | 9526011F1D2BBBA500080227 /* DNAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNAsset.h; sourceTree = ""; };
97 | 952601201D2BBBA500080227 /* DNAsset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNAsset.m; sourceTree = ""; };
98 | 952601221D2CD7C600080227 /* DNImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNImagePicker.h; sourceTree = ""; };
99 | 952601281D2D112500080227 /* DNAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNAlbum.h; sourceTree = ""; };
100 | 952601291D2D112500080227 /* DNAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNAlbum.m; sourceTree = ""; };
101 | 95A1472F1D6C15A900E80455 /* DNImagePickerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNImagePickerHelper.h; sourceTree = ""; };
102 | 95A147301D6C15A900E80455 /* DNImagePickerHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNImagePickerHelper.m; sourceTree = ""; };
103 | 95BE23281D73490700EDBAF3 /* DNAlbumCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNAlbumCell.h; sourceTree = ""; };
104 | 95BE23291D73490700EDBAF3 /* DNAlbumCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNAlbumCell.m; sourceTree = ""; };
105 | /* End PBXFileReference section */
106 |
107 | /* Begin PBXFrameworksBuildPhase section */
108 | 952600AA1D2B9D4100080227 /* Frameworks */ = {
109 | isa = PBXFrameworksBuildPhase;
110 | buildActionMask = 2147483647;
111 | files = (
112 | 952600F41D2BA29100080227 /* Photos.framework in Frameworks */,
113 | 952600F21D2BA28000080227 /* AssetsLibrary.framework in Frameworks */,
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | /* End PBXFrameworksBuildPhase section */
118 |
119 | /* Begin PBXGroup section */
120 | 952600A41D2B9D4100080227 = {
121 | isa = PBXGroup;
122 | children = (
123 | 952600C71D2B9D8400080227 /* DNImagePickerDemo */,
124 | 952600AF1D2B9D4100080227 /* DNImagePicker */,
125 | 952600AE1D2B9D4100080227 /* Products */,
126 | 952600F31D2BA29100080227 /* Photos.framework */,
127 | 952600F11D2BA28000080227 /* AssetsLibrary.framework */,
128 | );
129 | sourceTree = "";
130 | };
131 | 952600AE1D2B9D4100080227 /* Products */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 952600AD1D2B9D4100080227 /* DNImagePicker.app */,
135 | );
136 | name = Products;
137 | sourceTree = "";
138 | };
139 | 952600AF1D2B9D4100080227 /* DNImagePicker */ = {
140 | isa = PBXGroup;
141 | children = (
142 | 952601221D2CD7C600080227 /* DNImagePicker.h */,
143 | 952600CA1D2B9F6F00080227 /* Support */,
144 | 952600C91D2B9F5100080227 /* Resources */,
145 | 952600C81D2B9F3700080227 /* Classes */,
146 | );
147 | path = DNImagePicker;
148 | sourceTree = "";
149 | };
150 | 952600B01D2B9D4100080227 /* Supporting Files */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 952600B11D2B9D4100080227 /* main.m */,
154 | );
155 | name = "Supporting Files";
156 | path = ../DNImagePicker;
157 | sourceTree = "";
158 | };
159 | 952600C71D2B9D8400080227 /* DNImagePickerDemo */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 952600B31D2B9D4100080227 /* AppDelegate.h */,
163 | 952600B41D2B9D4100080227 /* AppDelegate.m */,
164 | 952600B61D2B9D4100080227 /* ViewController.h */,
165 | 952600B71D2B9D4100080227 /* ViewController.m */,
166 | 952601161D2BBB4A00080227 /* InfoViewController.h */,
167 | 952601171D2BBB4A00080227 /* InfoViewController.m */,
168 | 952601181D2BBB4A00080227 /* CollectionViewController.h */,
169 | 952601191D2BBB4A00080227 /* CollectionViewController.m */,
170 | 9526011A1D2BBB4A00080227 /* CollectionViewCell.h */,
171 | 9526011B1D2BBB4A00080227 /* CollectionViewCell.m */,
172 | 952600B91D2B9D4100080227 /* Main.storyboard */,
173 | 952600BC1D2B9D4100080227 /* Assets.xcassets */,
174 | 952600BE1D2B9D4100080227 /* LaunchScreen.storyboard */,
175 | 952600C11D2B9D4100080227 /* Info.plist */,
176 | 952600B01D2B9D4100080227 /* Supporting Files */,
177 | );
178 | path = DNImagePickerDemo;
179 | sourceTree = "";
180 | };
181 | 952600C81D2B9F3700080227 /* Classes */ = {
182 | isa = PBXGroup;
183 | children = (
184 | 952601241D2CDBAC00080227 /* Managers */,
185 | 952601151D2BB93C00080227 /* Models */,
186 | 952600D81D2BA17900080227 /* Views */,
187 | 952600CB1D2BA00700080227 /* Controllers */,
188 | );
189 | path = Classes;
190 | sourceTree = "";
191 | };
192 | 952600C91D2B9F5100080227 /* Resources */ = {
193 | isa = PBXGroup;
194 | children = (
195 | 952601011D2BAF6D00080227 /* imageResources.xcassets */,
196 | 952601071D2BAF7700080227 /* DNImagePicker.strings */,
197 | );
198 | path = Resources;
199 | sourceTree = "";
200 | };
201 | 952600CA1D2B9F6F00080227 /* Support */ = {
202 | isa = PBXGroup;
203 | children = (
204 | 24D077E8216F4BF2004E397A /* UIColor+Hex.h */,
205 | 24D077E9216F4BF2004E397A /* UIColor+Hex.m */,
206 | 952601091D2BB7F700080227 /* UIViewController+DNImagePicker.h */,
207 | 9526010A1D2BB7F700080227 /* UIViewController+DNImagePicker.m */,
208 | 9526010F1D2BB7F700080227 /* UIView+DNImagePicker.h */,
209 | 952601101D2BB7F700080227 /* UIView+DNImagePicker.m */,
210 | );
211 | path = Support;
212 | sourceTree = "";
213 | };
214 | 952600CB1D2BA00700080227 /* Controllers */ = {
215 | isa = PBXGroup;
216 | children = (
217 | 952600CC1D2BA05700080227 /* DNImagePickerController.h */,
218 | 952600CD1D2BA05700080227 /* DNImagePickerController.m */,
219 | 952600CE1D2BA05700080227 /* DNAlbumTableViewController.h */,
220 | 952600CF1D2BA05700080227 /* DNAlbumTableViewController.m */,
221 | 952600D01D2BA05700080227 /* DNImageFlowViewController.h */,
222 | 952600D11D2BA05700080227 /* DNImageFlowViewController.m */,
223 | 952600D21D2BA05700080227 /* DNPhotoBrowser.h */,
224 | 952600D31D2BA05700080227 /* DNPhotoBrowser.m */,
225 | );
226 | path = Controllers;
227 | sourceTree = "";
228 | };
229 | 952600D81D2BA17900080227 /* Views */ = {
230 | isa = PBXGroup;
231 | children = (
232 | 95BE23281D73490700EDBAF3 /* DNAlbumCell.h */,
233 | 95BE23291D73490700EDBAF3 /* DNAlbumCell.m */,
234 | 952600DB1D2BA26400080227 /* DNBrowserCell.h */,
235 | 952600DC1D2BA26400080227 /* DNBrowserCell.m */,
236 | 952600DD1D2BA26400080227 /* DNTapDetectingImageView.h */,
237 | 952600DE1D2BA26400080227 /* DNTapDetectingImageView.m */,
238 | 952600DF1D2BA26400080227 /* DNAssetsViewCell.h */,
239 | 952600E01D2BA26400080227 /* DNAssetsViewCell.m */,
240 | 952600E11D2BA26400080227 /* DNSendButton.h */,
241 | 952600E21D2BA26400080227 /* DNSendButton.m */,
242 | 952600E31D2BA26400080227 /* DNFullImageButton.h */,
243 | 952600E41D2BA26400080227 /* DNFullImageButton.m */,
244 | 952600E51D2BA26400080227 /* DNBadgeLabel.h */,
245 | 952600E61D2BA26400080227 /* DNBadgeLabel.m */,
246 | 952600E71D2BA26400080227 /* DNUnAuthorizedTipsView.h */,
247 | 952600E81D2BA26400080227 /* DNUnAuthorizedTipsView.m */,
248 | );
249 | path = Views;
250 | sourceTree = "";
251 | };
252 | 952601151D2BB93C00080227 /* Models */ = {
253 | isa = PBXGroup;
254 | children = (
255 | 9526011F1D2BBBA500080227 /* DNAsset.h */,
256 | 952601201D2BBBA500080227 /* DNAsset.m */,
257 | 952601281D2D112500080227 /* DNAlbum.h */,
258 | 952601291D2D112500080227 /* DNAlbum.m */,
259 | );
260 | path = Models;
261 | sourceTree = "";
262 | };
263 | 952601241D2CDBAC00080227 /* Managers */ = {
264 | isa = PBXGroup;
265 | children = (
266 | 95A1472F1D6C15A900E80455 /* DNImagePickerHelper.h */,
267 | 95A147301D6C15A900E80455 /* DNImagePickerHelper.m */,
268 | 24EBD7F8216CB58700B020FA /* DNImageFetchOperation.h */,
269 | 24EBD7F9216CB58700B020FA /* DNImageFetchOperation.m */,
270 | );
271 | name = Managers;
272 | sourceTree = "";
273 | };
274 | /* End PBXGroup section */
275 |
276 | /* Begin PBXNativeTarget section */
277 | 952600AC1D2B9D4100080227 /* DNImagePicker */ = {
278 | isa = PBXNativeTarget;
279 | buildConfigurationList = 952600C41D2B9D4100080227 /* Build configuration list for PBXNativeTarget "DNImagePicker" */;
280 | buildPhases = (
281 | 952600A91D2B9D4100080227 /* Sources */,
282 | 952600AA1D2B9D4100080227 /* Frameworks */,
283 | 952600AB1D2B9D4100080227 /* Resources */,
284 | );
285 | buildRules = (
286 | );
287 | dependencies = (
288 | );
289 | name = DNImagePicker;
290 | productName = DNImagePicker;
291 | productReference = 952600AD1D2B9D4100080227 /* DNImagePicker.app */;
292 | productType = "com.apple.product-type.application";
293 | };
294 | /* End PBXNativeTarget section */
295 |
296 | /* Begin PBXProject section */
297 | 952600A51D2B9D4100080227 /* Project object */ = {
298 | isa = PBXProject;
299 | attributes = {
300 | LastUpgradeCheck = 1000;
301 | ORGANIZATIONNAME = Dennis;
302 | TargetAttributes = {
303 | 952600AC1D2B9D4100080227 = {
304 | CreatedOnToolsVersion = 7.3.1;
305 | DevelopmentTeam = 7RQERF84NY;
306 | };
307 | };
308 | };
309 | buildConfigurationList = 952600A81D2B9D4100080227 /* Build configuration list for PBXProject "DNImagePicker" */;
310 | compatibilityVersion = "Xcode 3.2";
311 | developmentRegion = English;
312 | hasScannedForEncodings = 0;
313 | knownRegions = (
314 | en,
315 | Base,
316 | "zh-Hans",
317 | );
318 | mainGroup = 952600A41D2B9D4100080227;
319 | productRefGroup = 952600AE1D2B9D4100080227 /* Products */;
320 | projectDirPath = "";
321 | projectRoot = "";
322 | targets = (
323 | 952600AC1D2B9D4100080227 /* DNImagePicker */,
324 | );
325 | };
326 | /* End PBXProject section */
327 |
328 | /* Begin PBXResourcesBuildPhase section */
329 | 952600AB1D2B9D4100080227 /* Resources */ = {
330 | isa = PBXResourcesBuildPhase;
331 | buildActionMask = 2147483647;
332 | files = (
333 | 952600C01D2B9D4100080227 /* LaunchScreen.storyboard in Resources */,
334 | 952601051D2BAF7700080227 /* DNImagePicker.strings in Resources */,
335 | 952601031D2BAF6D00080227 /* imageResources.xcassets in Resources */,
336 | 952600BD1D2B9D4100080227 /* Assets.xcassets in Resources */,
337 | 952600BB1D2B9D4100080227 /* Main.storyboard in Resources */,
338 | );
339 | runOnlyForDeploymentPostprocessing = 0;
340 | };
341 | /* End PBXResourcesBuildPhase section */
342 |
343 | /* Begin PBXSourcesBuildPhase section */
344 | 952600A91D2B9D4100080227 /* Sources */ = {
345 | isa = PBXSourcesBuildPhase;
346 | buildActionMask = 2147483647;
347 | files = (
348 | 952600EB1D2BA26400080227 /* DNTapDetectingImageView.m in Sources */,
349 | 9526012A1D2D112500080227 /* DNAlbum.m in Sources */,
350 | 952600D61D2BA05700080227 /* DNImageFlowViewController.m in Sources */,
351 | 952600EC1D2BA26400080227 /* DNAssetsViewCell.m in Sources */,
352 | 952600D71D2BA05700080227 /* DNPhotoBrowser.m in Sources */,
353 | 952600EF1D2BA26400080227 /* DNBadgeLabel.m in Sources */,
354 | 952600B81D2B9D4100080227 /* ViewController.m in Sources */,
355 | 952600ED1D2BA26400080227 /* DNSendButton.m in Sources */,
356 | 952601211D2BBBA500080227 /* DNAsset.m in Sources */,
357 | 9526011D1D2BBB4A00080227 /* CollectionViewController.m in Sources */,
358 | 952600EE1D2BA26400080227 /* DNFullImageButton.m in Sources */,
359 | 952600D51D2BA05700080227 /* DNAlbumTableViewController.m in Sources */,
360 | 95BE232A1D73490700EDBAF3 /* DNAlbumCell.m in Sources */,
361 | 952600B51D2B9D4100080227 /* AppDelegate.m in Sources */,
362 | 952600B21D2B9D4100080227 /* main.m in Sources */,
363 | 952601141D2BB7F700080227 /* UIView+DNImagePicker.m in Sources */,
364 | 952601111D2BB7F700080227 /* UIViewController+DNImagePicker.m in Sources */,
365 | 952600D41D2BA05700080227 /* DNImagePickerController.m in Sources */,
366 | 24EBD7FA216CB58700B020FA /* DNImageFetchOperation.m in Sources */,
367 | 952600EA1D2BA26400080227 /* DNBrowserCell.m in Sources */,
368 | 9526011C1D2BBB4A00080227 /* InfoViewController.m in Sources */,
369 | 24D077EA216F4BF2004E397A /* UIColor+Hex.m in Sources */,
370 | 9526011E1D2BBB4A00080227 /* CollectionViewCell.m in Sources */,
371 | 952600F01D2BA26400080227 /* DNUnAuthorizedTipsView.m in Sources */,
372 | 95A147311D6C15A900E80455 /* DNImagePickerHelper.m in Sources */,
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | };
376 | /* End PBXSourcesBuildPhase section */
377 |
378 | /* Begin PBXVariantGroup section */
379 | 952600B91D2B9D4100080227 /* Main.storyboard */ = {
380 | isa = PBXVariantGroup;
381 | children = (
382 | 952600BA1D2B9D4100080227 /* Base */,
383 | );
384 | name = Main.storyboard;
385 | path = ../DNImagePicker;
386 | sourceTree = "";
387 | };
388 | 952600BE1D2B9D4100080227 /* LaunchScreen.storyboard */ = {
389 | isa = PBXVariantGroup;
390 | children = (
391 | 952600BF1D2B9D4100080227 /* Base */,
392 | );
393 | name = LaunchScreen.storyboard;
394 | path = ../DNImagePicker;
395 | sourceTree = "";
396 | };
397 | 952601071D2BAF7700080227 /* DNImagePicker.strings */ = {
398 | isa = PBXVariantGroup;
399 | children = (
400 | 952601061D2BAF7700080227 /* en */,
401 | 952601081D2BAFB200080227 /* zh-Hans */,
402 | );
403 | name = DNImagePicker.strings;
404 | sourceTree = "";
405 | };
406 | /* End PBXVariantGroup section */
407 |
408 | /* Begin XCBuildConfiguration section */
409 | 952600C21D2B9D4100080227 /* Debug */ = {
410 | isa = XCBuildConfiguration;
411 | buildSettings = {
412 | ALWAYS_SEARCH_USER_PATHS = NO;
413 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
414 | CLANG_ANALYZER_NONNULL = YES;
415 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
416 | CLANG_CXX_LIBRARY = "libc++";
417 | CLANG_ENABLE_MODULES = YES;
418 | CLANG_ENABLE_OBJC_ARC = YES;
419 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
420 | CLANG_WARN_BOOL_CONVERSION = YES;
421 | CLANG_WARN_COMMA = YES;
422 | CLANG_WARN_CONSTANT_CONVERSION = YES;
423 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
424 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
425 | CLANG_WARN_EMPTY_BODY = YES;
426 | CLANG_WARN_ENUM_CONVERSION = YES;
427 | CLANG_WARN_INFINITE_RECURSION = YES;
428 | CLANG_WARN_INT_CONVERSION = YES;
429 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
430 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
431 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
432 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
433 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
434 | CLANG_WARN_STRICT_PROTOTYPES = YES;
435 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
436 | CLANG_WARN_UNREACHABLE_CODE = YES;
437 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
438 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
439 | COPY_PHASE_STRIP = NO;
440 | DEBUG_INFORMATION_FORMAT = dwarf;
441 | ENABLE_STRICT_OBJC_MSGSEND = YES;
442 | ENABLE_TESTABILITY = YES;
443 | GCC_C_LANGUAGE_STANDARD = gnu99;
444 | GCC_DYNAMIC_NO_PIC = NO;
445 | GCC_NO_COMMON_BLOCKS = YES;
446 | GCC_OPTIMIZATION_LEVEL = 0;
447 | GCC_PREPROCESSOR_DEFINITIONS = (
448 | "DEBUG=1",
449 | "$(inherited)",
450 | );
451 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
452 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
453 | GCC_WARN_UNDECLARED_SELECTOR = YES;
454 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
455 | GCC_WARN_UNUSED_FUNCTION = YES;
456 | GCC_WARN_UNUSED_VARIABLE = YES;
457 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
458 | MTL_ENABLE_DEBUG_INFO = YES;
459 | ONLY_ACTIVE_ARCH = YES;
460 | SDKROOT = iphoneos;
461 | };
462 | name = Debug;
463 | };
464 | 952600C31D2B9D4100080227 /* Release */ = {
465 | isa = XCBuildConfiguration;
466 | buildSettings = {
467 | ALWAYS_SEARCH_USER_PATHS = NO;
468 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
469 | CLANG_ANALYZER_NONNULL = YES;
470 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
471 | CLANG_CXX_LIBRARY = "libc++";
472 | CLANG_ENABLE_MODULES = YES;
473 | CLANG_ENABLE_OBJC_ARC = YES;
474 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
475 | CLANG_WARN_BOOL_CONVERSION = YES;
476 | CLANG_WARN_COMMA = YES;
477 | CLANG_WARN_CONSTANT_CONVERSION = YES;
478 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
479 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
480 | CLANG_WARN_EMPTY_BODY = YES;
481 | CLANG_WARN_ENUM_CONVERSION = YES;
482 | CLANG_WARN_INFINITE_RECURSION = YES;
483 | CLANG_WARN_INT_CONVERSION = YES;
484 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
485 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
486 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
487 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
488 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
489 | CLANG_WARN_STRICT_PROTOTYPES = YES;
490 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
491 | CLANG_WARN_UNREACHABLE_CODE = YES;
492 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
493 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
494 | COPY_PHASE_STRIP = NO;
495 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
496 | ENABLE_NS_ASSERTIONS = NO;
497 | ENABLE_STRICT_OBJC_MSGSEND = YES;
498 | GCC_C_LANGUAGE_STANDARD = gnu99;
499 | GCC_NO_COMMON_BLOCKS = YES;
500 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
501 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
502 | GCC_WARN_UNDECLARED_SELECTOR = YES;
503 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
504 | GCC_WARN_UNUSED_FUNCTION = YES;
505 | GCC_WARN_UNUSED_VARIABLE = YES;
506 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
507 | MTL_ENABLE_DEBUG_INFO = NO;
508 | SDKROOT = iphoneos;
509 | VALIDATE_PRODUCT = YES;
510 | };
511 | name = Release;
512 | };
513 | 952600C51D2B9D4100080227 /* Debug */ = {
514 | isa = XCBuildConfiguration;
515 | buildSettings = {
516 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
517 | CODE_SIGN_IDENTITY = "iPhone Developer";
518 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
519 | DEVELOPMENT_TEAM = 7RQERF84NY;
520 | INFOPLIST_FILE = DNImagePicker/Info.plist;
521 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
523 | PRODUCT_BUNDLE_IDENTIFIER = com.awesomedennis.DNImagePickeraaa;
524 | PRODUCT_NAME = "$(TARGET_NAME)";
525 | PROVISIONING_PROFILE = "";
526 | };
527 | name = Debug;
528 | };
529 | 952600C61D2B9D4100080227 /* Release */ = {
530 | isa = XCBuildConfiguration;
531 | buildSettings = {
532 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
533 | CODE_SIGN_IDENTITY = "iPhone Developer";
534 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
535 | DEVELOPMENT_TEAM = 7RQERF84NY;
536 | INFOPLIST_FILE = DNImagePicker/Info.plist;
537 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
538 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
539 | PRODUCT_BUNDLE_IDENTIFIER = com.awesomedennis.DNImagePickeraaa;
540 | PRODUCT_NAME = "$(TARGET_NAME)";
541 | PROVISIONING_PROFILE = "";
542 | };
543 | name = Release;
544 | };
545 | /* End XCBuildConfiguration section */
546 |
547 | /* Begin XCConfigurationList section */
548 | 952600A81D2B9D4100080227 /* Build configuration list for PBXProject "DNImagePicker" */ = {
549 | isa = XCConfigurationList;
550 | buildConfigurations = (
551 | 952600C21D2B9D4100080227 /* Debug */,
552 | 952600C31D2B9D4100080227 /* Release */,
553 | );
554 | defaultConfigurationIsVisible = 0;
555 | defaultConfigurationName = Release;
556 | };
557 | 952600C41D2B9D4100080227 /* Build configuration list for PBXNativeTarget "DNImagePicker" */ = {
558 | isa = XCConfigurationList;
559 | buildConfigurations = (
560 | 952600C51D2B9D4100080227 /* Debug */,
561 | 952600C61D2B9D4100080227 /* Release */,
562 | );
563 | defaultConfigurationIsVisible = 0;
564 | defaultConfigurationName = Release;
565 | };
566 | /* End XCConfigurationList section */
567 | };
568 | rootObject = 952600A51D2B9D4100080227 /* Project object */;
569 | }
570 |
--------------------------------------------------------------------------------