iCarousel infinite scroll and index reset - ios

I am working with a carousel in iOS and I am trying to recreate the scrolling banners (featured images) that are present in the iOS app store and iTunes. I have a carousel variable and I would like to get that to scroll exactly like on the apps mentioned above. If you are not familiar with how they scroll, they slide the image and then stop for a period of time.
I have tried carousel.scrollByNumberOfItems(5, duration: 20) which just creates a constant scroll until it is finished. I have played around with different scrolling functions and cannot seem to achieve the desired effect. Again, I am looking for the image to slide, then pause, then slide the next, etc.
My second question is, when the images slide to the end of my images, how can I reset the index if it is passed in as a constant? In other words I am trying to achieve an infinite scrolling effect that will just keep cycling through my images one at a time, similar to the app store.
I am working in swift, but welcome objective c examples as well.
Any help is appreciated!
Thanks!

You can do this pretty easily with an NSTimer to initiate the scrolling.
For example this will scroll every 20 seconds, taking 5 seconds to scroll -
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.scrollTimer=[NSTimer scheduledTimerWithTimeInterval:20 target:self selector:#selector(scrollCarousel) userInfo:nil repeats:YES];
}
-(void) scrollCarousel {
NSInteger newIndex=self.carousel.currentItemIndex+1;
if (newIndex > self.carousel.numberOfItems) {
newIndex=0;
}
[self.carousel scrollToItemAtIndex:newIndex duration:5];
}
as long as your carousel is set to wrap then this will give you what you want.

Related

UIWebView Content Offset

I want to show a google.maps url into a UIWebView in my app but the page comes up in different point from this that i want. I tried everything of many questions here such as set contentOffset of webview.scrollview or contentInset or scrollsToTop or even with javascript commands but neither of them works.So this is the problem:
and this is the expected result that i would like to have:
I want my webpage to come up on top and not in the middle.
url: url
This has nothing to do with content offsets etc. - it is the page itself which scrolls down right after it finished loading. When loading the URL in Mobile Safari, you will get the exact same behaviour and can even observe the scrolling animation.
Unfortunately, there is nothing you can do to prevent it, except extracting the scroll code from the html the server delivers before loading it in the webview. This would be tedious and you shouldn't do it anyway, since this will likely break your app once changes are made by google to the inner workings of that page.
The only solution I can think of right now is to scroll the page back to top programmatically after it has scrolled down. I've tried it with the url you provided and it acutally works. To do this, implement webViewDidFinishLoad: in your webview delegate like so:
-(void)webViewDidFinishLoad:(UIWebView *)webView {
NSTimer *scrollTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(scrollBackToTop) userInfo:nil repeats:NO]; // Better make the timer an ivar
}
and implement a method like:
-(void)scrollBackToTop {
NSString* javascript = [NSString stringWithFormat:#"window.scrollTo(0, 0);"];
[theWebView stringByEvaluatingJavaScriptFromString:javascript];
}
This means of course that your webview will first scroll down visibly only to jump back to top, which is rather ugly. So you may want to hide the webview behind an opaque view containing an activity indicator or the like until the webview has loaded and finished all of the scrolling action...
Be aware though that, while less likely and less lethally, this may break as well. When I tried my solution, a 2 second delay was sufficient. If google slows down the animation in the future though, 2 seconds might not be enough and your scrollBackToTop method fires early. Since the java script will not cancel the scroll in progress, it won't scroll back to top at all.
Edit:
Maybe I have something better for you...
Do the following in your webViewDidFinishLoad: method:
NSString* javascript = [NSString stringWithFormat:#"document.getElementById('panel').style.position='fixed'; document.getElementById('panel').style.top='50px';"];
[webView stringByEvaluatingJavaScriptFromString:javascript];
This will completely suppress the scrolling animation. But it comes at a cost: If the user scrolls the webview manually now, the form fields remain fixed in position, while the rest of the page is scrolling normally.
So you need to undo the hack, by doing this:
NSString* javascript = [NSString stringWithFormat:#"document.getElementById('panel').style.position='absolute'; document.getElementById('panel').style.top='0px';"];
[theWebView stringByEvaluatingJavaScriptFromString:javascript];
You need to execute the second step with a delay again, after the scroll script has finished, otherwise the page will do the full scroll. For me, a 1.2 second delay did the trick.
You might want to prevent the user from scrolling during those 1.2 seconds by disabling scrolling on the webviews scrollview until the timer fires.
So there's still room for improvement, but this approach will probably make your app feel more responsive, compared to hiding the webview until it has scrolled back and forth...

multiple countdown timers in uitableview

I'm developing a native application clone of Snapchat or Facebook Poke.
I have a few issues related to timers and tap&hold functionality in received messages.
I have a viewcontroller (ViewControllerIncomingMessage) with a tableview which shows received messages and a UILongPressGestureRecognizer that opens a detail view (starts timer and update a countdown label. When the long press gesture ends I dismiss the view and schedule every second the following timer:
- (void)timerFired:(NSTimer *)timer {
[self.tableView reloadData];
}
This actually works but prevents rows from being deleted (because of reloadData of table)
Anyone has already implemented a functionality like that?
Please could you give me any hint about implementing timer update in the best way.

array's objects loss in storyboards's scene

I make a game that has 2 scenes (first-welcome screen with "start game" button, second - is the game") Game is simple: head-picture is trying to prevent collions with bullets(represented as uiimageviews in NSMutableArray *bullets) with the help of -(void)touchesMoved:withEvent:. If it collides UIAlertView appears to get user's choise: repeat or go to wellcome-scene. If we go to the game-scene first time then everything is OK.
The problem is when we go to the game-scene next time. the property bullets after initiation in viewDidLoad shows its count as 3(as it should), but latter it shows bullets.count == 0;
I don't know how is it possible - I initiate this array in method that calls only in viewDidLoad. And in the first time everything works properly.
P.S. duaring code I don't use propertyName, only self.propertyName.
P.P.S I suggest reason in [UIView commitAnimations] - that's how I make bullets animation.
If I //hide it. evetything is OK. But without animation it looks poor.
Instead of calling the method in viewDidLoad, try calling it in viewDidAppear to set the count to 3 each time the view appears, because it should only be loaded into memory once, but viewDidAppear is called each time the view will show.

Here's The CA Animation Sequencing Sitch

I asked a question (Animation Sometimes Doesn't Occur) a while ago about an animation not, apparently, happening sometimes. I got no helpful answers. So, after much research and playing around, I discovered that sometimes the animation that is supposed to happen second, sometimes happens first. The other one does happen, just not when it is expected to happen. The two animations are "flip" and "disappear." As an example, there are four tiles. When one tile is touched, it flips. When a second tile is touched it is supposed to flip. If the tiles match, both tiles are disappeared. If they are not matched, the tiles flip back. The flipback animation has always occurred correctly, so far as I have been able to tell. In other words - the first tile is flipped. The second tile is flipped. The tiles do not match. The two tiles flipback. As for when the tiles match, the first tile flips correctly. Sometimes the second tile flips correctly and then they both disappear (animation group of rotate and shrink). Sometimes the second tile does not flip correctly, but they both disappear before the second tile does its flip. This is not acceptable.
This is what I have tried so far - I have tried NSThread pausing. That didn't work because the whole thread was paused, which didn't let the animation that hadn't occurred occur. I looked into NSTimer - but the method that is being called has two parameters which means I have to do NSInvocation and I haven't figured that out yet - and not sure it would work. Right now, I have put in a flag that marks when flip animations are completed. If this method eventually works, I have to figure out how to account for flipping individual tiles over and back again without upping the completion count. Anyway - using this method, I need to figure out how to tell my second animation to wait until the first animation is completed before running.
What I would ideally like to be able to do is to tell the disappear animation to always wait until the second tile is completely flipped before committing.
What I can't figure out is a) why sometimes the animations happen in the correct order, sometimes they don't and b) when the animations are trying to not happen in the correct order, how to force them to occur in the correct order.
Not really sure what code would be helpful for you to see. Ask and I shall provide!
Here is the code that calls the animations:
-(void)buttonPressed: (UIButton*)buttoni
{
[self flipTiles:(UIButton *)buttoni];
[self twoTilesFlipped];
}
Clearly, the flipTiles animation is called first. What I don't understand is why it sometimes isn't called until after the code that is called in twoTilesFlipped. I thought that programming was about logic and this just doesn't make logical sense to me. Oh, I just had a thought...I am going to put in a NSTimer delay in this code - maybe that will do the trick!
That seems to have done the trick. There are some tweaks that I obviously need to fix now, but at least it works everytime.
This is what I added:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(twoTilesFlipped)
userInfo:nil
repeats:NO];
so the final code for the method was:
-(void)buttonPressed: (UIButton*)buttoni
{
[self flipTiles:(UIButton *)buttoni];
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(twoTilesFlipped)
userInfo:nil
repeats:NO];
}

Why can't I update the contents of my UIScrollView using NSOperationQueue / NSOperationInvocation?

I think I remember something about UI being updated on the main thread, could be the explanation, however my issue is that I have a UIScrollView with 1000+ images in it, and I wrote a routine that quickly will toggle the images visible in the view to show their real image, and when out of visible view, they switch to a placeholder image. All the offscreen images share the same placeholder, greatly reducing memory load.
I wrote two methods that toggle the next few tiles of the view on/off, and are kicked off if you have scrolled enough in a certain direction. The scrolling is detected via the UIScrollViewDelegate callback method scrollViewDidScroll.
This strategy works fine, but the scrollview scrolling is a little jittery on slow devices (iPad 1). I wanted to increase performance, so I thought I could change the code so that the two methods that update the scrollview contents were NSOperationInvocation, added to an NSOperationQueue.
However, when I do this, even with priority set to VeryHigh, the routines to not update the UI even though they seem to be called, and the queue does grow, when scrolling. The observed behavior is that the images retain their placeholder images and do not switch on.
Why doesn't this work?
Code for the NSOperationInvocation:
ImageThumbView *thumb = [boardThumbsArray objectAtIndex:lowestLoadedThumbTag - i];
[loadedThumbsArray addObject:thumb];
[thumb showThumbImage];
ImageThumbView is a UIButton Subclass
- (void)showThumbImage {
if (thumbImagePath != nil) {
thumbImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:thumbImagePath]]];
} else {
NSLog(#"%#", #"Cannot show thumb image: thumbImagePath is nil");
}
[self setBackgroundImage:thumbImage forState:UIControlStateNormal];
[self setNeedsDisplay];
}
Look at Apple's "PhotoScroller" sample code. You should not be having 1000 views as subviews of scrollview. Recycle the ones that are no longer visible.
Also look at WWDC 2010 "Designing apps with scrollview" video. That explains the photoscroller sample code
Thanks

Resources