Using UICollectionView in an SKScene to implement horizontal scrolling menu - ios

I am implementing a horizontal carousel-style character selection screen for a game (as per image below).
Image of carousel effect
The app is structured as one main GameViewController presenting different scenes; the CharacterSelectionScene being one of them.
From my research it seems that, although not always advisable to mix UIKit and SpriteKit elements, the best way to achieve the effect is the use a UIColectionView and add it as a subview to the scene. Because it takes care of the some of the animation and bounce effects.
Horizontal scrolling in SpriteKit (vs. a viewcontroller)
However, it's giving me a real headache! Using the post above as an example, I subclassed UICollectionView but I am unable to use the CharacterSelectionScene as the datasource and delegate! This would be ideal as the scene is where the data is loaded in from a plist.
I am currently using my CharacterCollectionView as the datasource and delegate by passing data from the scene via the collection view's init() a la:
collectionView = CharacterCollectionView(frame: customFrame, collectionViewLayout: layout, characterData: characterData)
This works but feels like a bad idea, it feels like a bit of a bodge. Maybe I'm wrong but as a fairly new programmer I'd just like to do this the right way!
Can anyone point me in the right direction? Am I going down completely the wrong path here or is this a perfectly good way to move forward. All advise/pointers appreciated!

Related

How is the Instagram Stories cube transition done in iOS?

When swiping between stories in Instagrams new feature "Stories" (you know that cube-like transition when going from one story to another) I can't manage to understand how they do it!
First of all, if you dig deeper into the functionality you find that it works exactly like the UIPageViewControllers transition:
- It bounces when swiping fast from one view to another.
- You can pause the swipe in the middle of the transition by touching the screen.
The developing team couldn't have used a solution based on the more known workarounds out there, e.g:
https://www.appcoda.com/custom-view-controller-transitions-tutorial/
Because as far as I know my two statement above is not possible to achieve with anything else than the PageViewController.
This leaves me thinking that the Instagram Developer Team gained access to a new transition style for the PageViewController, also known as Cube-scroll, or is it a workaround that I'm not aware of?
Any ideas?
I took a shot at recreating this functionality a while back. You can check the source code on GitHub: https://github.com/oyvind-hauge/OHCubeView
I'm using a scroll view (with paging enabled) and, for each subview I'm manipulating these as a function of the given view's current x-offset in the scroll view. The actual animations are done on each subview's layer using Core Animation (more specifically, transforming an identity matrix, given by CATransform3DIdentity, using the method CATransform3DRotate).
The shadow effects are also applied to the subview's layers (view.layer.opacity), with the amount of shadow determined by how much of the view is showing on screen.
My implementation solves both of your concerns (bounces when swiping, can pause swipes). I'm sure this could have also been implemented using the a UIPageViewController, but I hate working with those.
I think you are overthinking the controller's part here. The effect can easily be achieved using a CATransformLayer and three-sided cube-like view structure, where there is one view which aligns with the screen plane, and two others rotated -90 and 90 degrees on their y axis. Then, getting a pan gesture to rotate the scene. After a successful 90 degree turn (in either direction), you can either quickly reset the scene (so that keeping on rotating appears as if continues, but actually the camera shifted back to initial position) or you can have a full 360 degree rotation, and just update previous and next "pages". A single controller can handle this scene. If you prefer to have each page as a controller, it is possible, you can still use one controller for the scene, and then use the page controllers as child controllers, and setting their views as described above.
See this article for more information on CATransformLayer. Their example already creates something that is quite close to what you need.

Load Multiple Separate Swift Files into Main Container View

Ok, so I will apologize in advance, but I am a complete noob to Swift and iOS development, but I really want to learn to code. I have followed quite a few tutorials and so forth online, but cannot seem to find an answer for this problem I am having. There has to be a simple solution to this because it doesn't seem like a very hard issue but the googles are not being my friend in finding an answer. I do not want to use storyboards because I want to learn the real meat and potatoes. I am using OS X 10.11, Xcode 7, writing the app for iOS 9, universal.
So, I designed a calendar app with quite a unique display, UI, and functionality than the other grid based calendars out there. I have a UIView that I want to be a container to hold the other views I need and pull them into the container view. The files I have are the included ViewController.swift and my custom files ContainerView.swift HeaderView.swift, CalView.swift, and CalDetailView.swift. I set classes for each file, the HeaderView is a basic UIView, CalView is a horizontal UIScrollView that enables pagination for the different calendar views like week, month, day, year, and so on. The CalDetailView is also a horizontal UIScrollView that will display event details to the user and also be the primary action area for the user for editing, adding events, etc.
Currently the ContainerView loads just fine and I can do whatever I want there and can create these other subviews without a problem but only in the ContainerView file. I want to keep these areas separated out into different files for my sanity and add them into ContainerView UIView as subViews with AutoLayout and everything, just like I am able to do inside the ContainerView file, but it would be enormous and I don't want that.
I believe the proper way to do this is to add these subViews under the viewDidLoad() method of the main VC and create my AutoLayout constraints in the VC file, then I just want to load my subViews in the ContainerView file and build the screen. The separate subView files will contain all of my drawing code and touch events and so forth for the views.
Here's a simple wireframe of what I am trying to accomplish...
The whole window is ContainerView.swift the rest, subViews of ContainerView.
WireFrame
This question is a little open ended and non specific, but let's ignore this for now (it is your first time), in future please be more specific, this is the kind of response a tutorial might be better providing. You will have enough to do, without avoiding Storyboards - feel free to use them.
In any case it is fine.
Given a UIView subclass MyView, in your main view controller:
override func viewDidLoad() {
super.viewDidLoad()
....
let myView = MyView()
self.view.addSubView(myView)
myView.frame = ... OR <SET CONSTRAINTS>
....
}
Essentially you will initialise those view subclasses and add them as appropriate.

Scroll View in SpriteKit

I want to make a vertical scrolling view for the level selector on my SpriteKit game, I don't know if I have to use UIScrollView or make it using the SpriteKit framework. Please if anyone knows the best way to do it and how let me know. Thanks.
You have several options here.
It is possible to integrate UI elements into SpriteKit, but instead of adding children to self (your scene), you would add subviews to self.view. You would of course, work with the view now instead of a scene so theres a different way of positioning elements which you would have to work out. Theres quite a few examples of how to do this, here's one that might help you.
An alternative is using something like Scroll Kit, which helps you integrate a UIScrollView into SpriteKit very conveniently!
Also check out this question which might be exactly what you're looking for. Hope this helps!

Who should manage the UI Elements, the view or the view controller?

I am currently developing an iOS app and I was wondering how to manage the UI elements. I am using a Storyboard to place my views and Autolayout to make everything resolution independent. If it helps, here's a bit of background on how I came up with this question.
Some Backgroud
I have buttons the represent piano keys and I later in code add a subview to these that draws the actual keys on them. I did this by creating #IBOutlets on the ViewController and susbscribed to the UIDeviceOrientationDidChangeNotification. This called a method that adds the subviews based on the current button frames to get the appropriate sized keys.
This worked fine when running in iOS 8.1, but if I ran the app on iOS 7, the frames of the buttons weren't updated to the new orientation by the time I got the UIDeviceOrientationDidChangeNotification, so everything was messed up in landscape. I did a little research (UIInterfaceOrientation not yet updated when UIDeviceOrientationDidChangeNotification caught in UIView) and it seems that a good solution would be to override the layoutSubviews method. Problem is, layoutSubviewsis a UIView method, and I am managing my buttons and UI in my UIViewController.
Impulsively I wanted to subclass my UIView, override layoutSubviews and from there call a method on my Controller to add the keys to the buttons correctly, but that doesn't sound right.
The Questions
My UI is managed by the UIViewController. But I need to update my views based on a method proper of a UIView. I assume, to respect the MVC principles, that my view should't now a thing about my controller, but then this brings up a few questions:
Who should be managing the UI?
Is my strategy wrong and should the
UIView hold the #IBOutlets to the buttons so that it can later
apply the subviews I need them to have?
If you read the background, do you have a suggestion for this particular situation?
I assume the complexity of this problem is relatively small and I don't need to setup notifications in NSNotificationCenter, but I may be wrong. I would really like to hear this is not the only solution.
Thanks in advance. I hope I was clear enough, but if you want/need any additional details on my particular situation, let me know and I will gladly elaborate.
if I understood the question correctly, your ViewController should be laying out the keys within it's view. A good, but not the only, place to do this is in viewDidLayoutSubviews which a method you can override on UIViewController.
Now if your views should maintain their internal layout. i.e if you buttons/keys have any subviews, you should update those in layoutSubviews on UIView as you mentioned.
Both methods will be called in response to changes in the bounds or center of your parent view.
As far as rotation changes are concerned, in iOS 8, you should use viewWillTransitionToSize:withTransitionCoordinator: or willTransitionToTraitCollection:withTransitionCoordinator:
depending on your needs.
I highly recommend that you write your layout independent of orientation. You should just use the containing view's bounds for reference and never hard code in any frames. For example perhaps one of your keys should be 1/56 the width of it's superview instead of a magical number for portrait and landscape.

Autoscrolling in a UIScrollview

I have been only using Xcode 5 for a little while now and I need help when it comes to auto scrolling a UIScrollView. I am using a single view application. I need the screen to scroll down at a pace that speeds up incrementally. Also I need the screen to keep progressing even when the screen is touched. If someone can explain which code goes where it would be great! Your help will be greatly appreciated. :)
Check out this library: https://github.com/danielamitay/DAAutoScroll
It stops to scroll when the user touches the screen and that's the only solution I see possible. I don't even see why you wouldn't want the user to be able to stop the scrolling..
OK, just adding this from your duplicate question.
I suspect the Piano Tiles game is actually using something like Sprite Kit.
This allows a lot more control over thing like "scrolling" speed.
Instead of using a UIScrollView you would use an SKNode as a layer with the buttons added to that parent layer.
Then using the update game loop you can incrementally increase the speed of the movement based on the time since the game started.
In essence... don't use UIScrollView, don't use UIKit, use SpriteKit.
I can see a few options:
1) suggested by Fogmeister, use Sprite Kit instead.
2) see setContentOffset
3) just use a normal view as parent, then have another child view on top with the full content (would be longer than the parent view), create a NSTimer to periodically call a method which scrolls the child view in whatever direction and speed as required.
Note that might need something on top to mask around the child view from showing the suppose-to-be-hidden sections of the child view.
Hope this helps

Resources