My task is pretty simple and my code works, it's just that my code feels a bit clumsy to me (and probably will for you too).
I have a view controller (HomeViewController
) with a scrollView
, inside this scroll view I have a label, and the scroll view is set to scroll horizontally. So now we have a view controller with a label and you can scroll this label.
What I want to do here is, whenever I scroll down the label a V sign icon will come from top, and whenever I the scroll view property contentOffset.y <= -73
I want to change the V sign icon to a different V sign icon.
I have some more parameters for changing this label. For instance, if there is even a label, because I take this label from a table view of another view controller and I can delete objects from this table view, and if there are no objects in this table view there is no label, in this case I don't want to present those icons when scrolling (this is also something I did in a pretty clumsy way, I think the best will be to disable the scroll view in this case).
This is my code (the relevant code, I'm working with nib's just so you know):
HomeViewController.m:
#import "HomeViewController.h"
//there are some more classes I'm importing here
@interface HomeViewController () <StackTableViewControllerDelegate, UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *currentScrollImage; //size 50X50
@property (weak, nonatomic) IBOutlet UIImageView *vMarkIcn; //size 28X20
@property (weak, nonatomic) IBOutlet UIImageView *greenVmarkIcn; //size 50X50
@property (assign, nonatomic) BOOL labelRemoving;
@end
@implementation HomeViewController {
int fingerLiftedAtOffset;
}
//stackTableViewController is the table view where im taking the strings to populate the label
- (id)init {
self = [super initWithNibName:@"HomeViewController" bundle:nil];
if (self) {
// Do something
stackTableViewController = [[StackTableViewController alloc] init];
stackTableViewController.delegate = self;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.homeLabel.text = stackTableViewController.currentTarget;
self.myScrollView.delegate = self;
if (![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.vMarkIcn.image;
}
}
//here is the action/mess/clumsiness :)
- (void)viewWillAppear:(BOOL)animated {
[stackTableViewController fetchData];
self.homeLabel.text = stackTableViewController.currentTarget;
[self.myScrollView becomeFirstResponder];
}
// here the scroll view icn's are updated according to the offset
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
//AudioServicesPlaySystemSound(soundEffect3);
if (![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.vMarkIcn.image;
}
if (self.myScrollView.contentOffset.y <= -73 && ![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.greenVmarkIcn.image;
}
NSLog(@"%f", self.myScrollView.contentOffset.y);
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (![stackTableViewController isEmpty] && fingerLiftedAtOffset <= -73) {
if (![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.vMarkIcn.image;
}
[stackTableViewController removeObjectFromStack];
if (![stackTableViewController isEmpty]) {
AudioServicesPlaySystemSound(soundEffect2);
}
} else {
self.currentScrollImage.image = nil;
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSLog(@"finger was lifted");
fingerLiftedAtOffset = self.myScrollView.contentOffset.y;
if (self.myScrollView.contentOffset.y <= -73 && !self.labelRemoving && ![stackTableViewController isEmpty]) {
[UIView animateWithDuration:1.5
animations:^{
self.homeLabel.frame = self.view.frame;
}];
}
}
- (void)viewWillAppear:(BOOL)animated {
[stackTableViewController fetchData];
self.homeLabel.text = stackTableViewController.currentTarget;
[self.myScrollView becomeFirstResponder];
}
// here the scroll view icn's are updated according to the offset
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
//AudioServicesPlaySystemSound(soundEffect3);
if (![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.vMarkIcn.image;
}
if (self.myScrollView.contentOffset.y <= -73 && ![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.greenVmarkIcn.image;
}
NSLog(@"%f", self.myScrollView.contentOffset.y);
}
// here i'm removing the label from the stack
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (![stackTableViewController isEmpty] && fingerLiftedAtOffset <= -73) {
if (![stackTableViewController isEmpty]) {
self.currentScrollImage.image = self.vMarkIcn.image;
}
[stackTableViewController removeObjectFromStack];
if (![stackTableViewController isEmpty]) {
AudioServicesPlaySystemSound(soundEffect2);
}
} else {
self.currentScrollImage.image = nil;
}
}
// this is a method to add animation when the finger is lifted so the new label will come from top
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSLog(@"finger was lifted");
fingerLiftedAtOffset = self.myScrollView.contentOffset.y;
if (self.myScrollView.contentOffset.y <= -73 && !self.labelRemoving && ![stackTableViewController isEmpty]) {
[UIView animateWithDuration:1.5
animations:^{
self.homeLabel.frame = self.view.frame;
}];
}
}
StackTableViewController.m (only relevant code):
@interface StackTableViewController () <NSFetchedResultsControllerDelegate>
@end
@implementation StackTableViewController
- (id)init {
self = [super initWithNibName:@"StackTableViewController" bundle:nil];
if (self) {
[self fetchData];
}
return self;
}
- (void)fetchData {
[self.fetchedResultController performFetch:nil];
if (self.fetchedResultController.fetchedObjects.count > 0) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *current = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = current.body;
}else {
self.currentTarget = nil;
}
}
- (BOOL)isEmpty {
if (self.fetchedResultController.fetchedObjects.count > 0) {
return NO;
} else {
return YES;
}
- (void)removeObjectFromStack {
if (self.fetchedResultController.fetchedObjects.count > 0) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
[self tableView:self.tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
[self.fetchedResultController performFetch:nil];
[self fetchData];
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
Target *target = [self.fetchedResultController objectAtIndexPath:indexPath];
CoreDataStack *stack = [CoreDataStack defaultStack];
[[stack managedObjectContext] deleteObject:target] ;
[stack saveContext];
if ([_delegate respondsToSelector:@selector(didDeleteObject)]) {
[self fetchData];
[_delegate didDeleteObject];
}
}
HomeViewController nib file documents outline:
So, it works, but I guess the code is bad.
I guess I need to only use 1 UIImageView
and set its image, but I don't know how to do it with resizing the images how I want to, and now the V sign icon looked stretched, although I made currentScrollImage
to be scroll to fill.
Something else I did weird is that I added two image objects to my HomeViewController
nib file, and added them to the scroll view, and I set their initial position to x=146, y = -50
, and set them to be hidden in the IB, so when I scroll they will come down and I can change the image accordingly.