-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to remove an item from image viewer #101
Conversation
@humblehacker many thanks for the effort!. We need take a look at this.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheers for the PR, nice work! 🚀
A few comments here and there, please address these before we can merge it 🏎
func provideGalleryItem(_ index: Int) -> GalleryItem { | ||
|
||
let imageView = imageViews[index] | ||
return items[imageView]! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use guard
or if let
instead of !
?
@@ -20,12 +20,41 @@ class ViewController: UIViewController, GalleryItemsDataSource, GalleryDisplaced | |||
@IBOutlet weak var image6: UIImageView! | |||
@IBOutlet weak var image7: UIImageView! | |||
|
|||
var imageViews: [UIImageView] = [] | |||
var imageViews: [UIImageView] = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally not a big fan of this type of indentation... but whatever :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem. I've got AppCode set up to do this for me, but I can turn it off for this.
|
||
let imageView = imageViews[index] | ||
imageView.removeFromSuperview() | ||
imageViews.remove(at: index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't we need to remove the item from items
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is just test code, and not really how one would implement a view like this, I didn't see the need to keep the two structures in sync - the dictionary will always contain a superset of the data in the array, with no real downside. If you prefer, I can come up with a cleaner and more representative example at the expense of additional code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, we want to keep the example as simple as possible. In this case, for the sake of "completeness", I'd say let's just remove the item from items
too. Just to show that the consumer is responsible for managing both of these fields... maybe expanding a bit on the idea with a comment?
@@ -440,7 +444,9 @@ | |||
TargetAttributes = { | |||
C7897CE11C1350B7006447FB = { | |||
CreatedOnToolsVersion = 7.1.1; | |||
DevelopmentTeam = LVJ3X3W924; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah 💣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops
@@ -619,6 +627,8 @@ | |||
isa = XCBuildConfiguration; | |||
buildSettings = { | |||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||
DEVELOPMENT_TEAM = LVJ3X3W924; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💣
@@ -632,6 +642,8 @@ | |||
isa = XCBuildConfiguration; | |||
buildSettings = { | |||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||
DEVELOPMENT_TEAM = LVJ3X3W924; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💣
static func deleteButton() -> UIButton { | ||
|
||
let button = UIButton(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 80, height: 50))) | ||
button.setTitle("Delete", for: UIControlState()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for: .normal
no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. This was a copy/paste from one of the other existing button methods, and I hadn't noticed the UIControlState()
argument.
@@ -16,7 +16,7 @@ final class GalleryPagingDataSource: NSObject, UIPageViewControllerDataSource { | |||
|
|||
fileprivate let configuration: GalleryConfiguration | |||
fileprivate var pagingMode = GalleryPagingMode.standard | |||
fileprivate let itemCount: Int | |||
fileprivate var itemCount: Int { return itemsDataSource!.itemCount() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try to avoid !
if at all possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I started with Swift, I took a very strict approach with optionals, essentially never force unwrapping. I've since relaxed that view. In cases where optionals are guaranteed to be non-nil or would be a programmer error if they were, force unwrapping and the resultant crash are the way to go, as it allows finding the problem early. I found guard let
with fatalError()
to be unnecessary extra code.
In this case, attempting to use this class without an itemsDataSource defined would be a programmer error.
Another point is that propagating optionals can result in unnecessary complexity as the optional must be dealt with at multiple levels, so I avoid returning optionals unless it really makes sense for the interface.
That said, if you guys prefer to keep force unwrapping out, I'm fine with following your convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely agree with you, I try to follow a very similar approach when it comes to !
In this specific case I feel like it'd be reasonable to return 0
for itemCount
in case the dataSource isn't set. How would return itemsDataSource?.itemCount() ?? 0
make you feel? :)
if let closeButton = closeButton { | ||
closeButton.addTarget(self, action: #selector(GalleryViewController.closeInteractively), for: .touchUpInside) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Thanks so much for taking the time to review my contribution! For the sake of review, do you guys prefer additional commits with the review changes, or amending of the original commit? |
Thanks for contributing @humblehacker! |
Pushed too soon. Please stand by ;) |
e0ff242
to
3350cd0
Compare
@zfoltin Ok, second try. I think this implementation of |
Cheers for the work @humblehacker great stuff! 👍 |
This solution works well in my testing, but there may be some aspect I've missed. I'm open to suggestions for improvement/alternate approaches.