Showing posts with label swift2. Show all posts
Showing posts with label swift2. Show all posts

Wednesday, March 7, 2018

Debug console not showing values for Swift + Objective-C

Leave a Comment

My app uses Swift and a 3rd-party library in Objective-C. When my debugger steps into the Objective-C code, the debug console does not show the values of my Swift string correctly. Instead, it shows unable to read data. How can we resolve this issue?

enter image description here

3 Answers

Answers 1

If you are using xcode 7.3 you can debug swift classes but xcode less than 7.3 you can debug for objective c class. Both swift and objective c support is not there. You can copy paste those objective c variables and you can print objective c variables by "po objectiveC_variable".

Answers 2

I suppose you might be using objective C bridging header also to use objective c library in Swift. I see both email and password is shown as Swift._NSContiguousString.And that may be the case if the bridging header that you made for your library might be giving some problem or not executing properly ,not sure. Because if the bridging was working then Swift._NSContiguousString would have been treated as "NSString" and you could convert it to as "String" simply.This is what I think ,you can jus check on the bridging header.

Answers 3

you can use po {{variable_name}} on lldb for print runtime value and also use e {{variable_name}} for print and e {{variable_name}} = {{value}} for set new value.

attention: when you use po autocomplete work, but when use e autocomplete doesn't work.

Read More

Wednesday, October 5, 2016

Login Logout for ViewController and TabBarViewcontroller? APPLE TV

Leave a Comment

would someone have any experience with this type of layout? I have a Initial ViewController that is used for Login then after Login it goes to a TabBarViewController as presentViewController() from the LoginViewController. All of this works well and logout but once I log out and re-login in the same session it looks like it creates another Tabbarviewcontroller ontop and then crashes the app. Bellow is the image with the storyboard layout

let mainStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())     let vc : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarViewController") as UIViewController     self.presentViewController(vc, animated: true, completion: nil) 

enter image description here

1 Answers

Answers 1

Does this help answer your question? http://sketchytech.blogspot.sg/2012/11/instantiate-view-controller-using.html

Possibly relevant text:

Note: if the presented view controller and the presenting view controller are the same class then do not place presentation code in viewDidAppear: because this would mean view controllers were created infinitely.

Read More

Wednesday, June 29, 2016

Why can I not place Master and Detail view next to each other in UISplitViewController on the first run, but upon rotation it works?

1 comment

I have a split view controller that has a list of items on the left and a detail view on the right. Relevant code in AppDelegate:

let splitViewController = mainView.instantiateViewControllerWithIdentifier("initial") as! UISplitViewController            let rightNavController = splitViewController.viewControllers.last as! UINavigationController         let detailViewController = rightNavController.topViewController as! DetailsIpad          let leftNavController = splitViewController.viewControllers.first as! UINavigationController         let masterViewController = leftNavController.topViewController as! MainViewController          masterSplitViewController = masterViewController         detailSplitViewController = detailViewController          // Override point for customization after application launch.         let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController         navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()         splitViewController.delegate = self          self.window!.rootViewController = splitViewController 

When I first launch the app I see that the right part of the split screen takes up all of the screen:

enter image description here

If I rotate the screen, it becomes properly set (probably because both views are present on the screen):

enter image description here

When I set breakpoints everywhere, I see that the detail view on the right gets loaded before the master view on the left (list of items), despite not being called directly. I cannot change the order in which the views of the split screen are called. How can I fix this?

1 Answers

Answers 1

It's the default behavior of UISplitViewController. Have a close look at the following-

// An animatable property that controls how the primary view controller is hidden and displayed. A value of `UISplitViewControllerDisplayModeAutomatic` specifies the default behavior split view controller, which on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape. @property (nonatomic) UISplitViewControllerDisplayMode preferredDisplayMode NS_AVAILABLE_IOS(8_0); 

Here's the key part from same definition-

on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape.

Also, if you want to query the current state (display mode) of a UISplitViewController you should use this property-

// The actual current displayMode of the split view controller. This will never return `UISplitViewControllerDisplayModeAutomatic`. @property (nonatomic, readonly) UISplitViewControllerDisplayMode displayMode NS_AVAILABLE_IOS(8_0); 

And remember, you can't compare this with UISplitViewControllerDisplayModeAutomatic because-

This will never return UISplitViewControllerDisplayModeAutomatic.

My suggestion would be to set preferredDisplayMode to the value you want. In your case, it seems like you need the primary (master) to always be visible. So here's the proposed solution-

mySplitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible 

Why it loads the secondary(detail) controller first?

As you can see, a UISplitViewController instance always needs a detail view no matter what displayMode it is in currently. So it's a good call to

  • load the detail view first.
  • load the primary view after (conditionally based on displayMode).

Hope this helps.

Read More

Thursday, April 14, 2016

How to Stop UIWebView from “bouncing” vertically scrolling bottom?

Leave a Comment

My question is the same as this question, but has one difference. When I scroll to top refresh my website, I want stop bouncing only to the end of the bottom scroll. How do I do this?

2 Answers

Answers 1

You can try like this :

override func viewDidLoad() {     super.viewDidLoad()      webview.scrollView.delegate = self  }  func scrollViewDidScroll(scrollView: UIScrollView) {      if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) {         scrollView.setContentOffset(CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height - scrollView.frame.size.height), animated: false)     }    } 

Set the delegate of your webview and set the content offset of the webview's scrollview

Ref taken from: http://stackoverflow.com/a/14084747/4557505

Answers 2

I think you can also set the scrollview's bounces

like this,It's simple

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{     if (scrollView.contentOffset.y > 0) {         scrollView.bounces = NO;     }else{         scrollView.bounces = YES;     } } 
Read More

Friday, March 11, 2016

SKAudioNode() crashes when pluggin in/out headphones

Leave a Comment

I am using a SKAudioNode() to play background music in my game. I have a play/pause function and everything is working fine until I plug in my headphones. There is no sound at all and when I call the pause/play function I get this error

AVAudioPlayerNode.mm:333: Start: required condition is false: _engine->IsRunning() com.apple.coreaudio.avfaudio', reason: 'required condition is false: _engine->IsRunning()

Does anyone knows what this means?

Code:

import SpriteKit  class GameScene: SKScene {  let loop = SKAudioNode(fileNamed: "gameloop.mp3") let play = SKAction.play() let pause = SKAction.pause() var isPlaying = Bool()  override func didMoveToView(view: SKView) {       loop.runAction(play)     isPlaying = true     self.addChild(loop) }  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {     _ = touches.first as UITouch!      for _ in touches {         if isPlaying {             loop.runAction(pause)             isPlaying = false         } else {             loop.runAction(play)             isPlaying = true         }      } } } 

1 Answers

Answers 1

I was not able fix it, but by using AVAudioPlayer() I found a good workaround. Thank you all for supporting me!

import SpriteKit import AVFoundation  class GameScene: SKScene {         var audioPlayer = AVAudioPlayer()        override func didMoveToView(view: SKView) {                 initAudioPlayer("gameloop.mp3")             }      override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {                 _ = touches.first as UITouch!         for _ in touches {             toggleBackgroundMusic()                     }             }      func initAudioPlayer(filename: String) {                 let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)         guard let newURL = url else {             print("Could not find file: \(filename)")             return         }         do {             audioPlayer = try AVAudioPlayer(contentsOfURL: newURL)             audioPlayer.numberOfLoops = -1             audioPlayer.prepareToPlay()             audioPlayer.play()         } catch let error as NSError {             print(error.description)         }             }      func toggleBackgroundMusic() {                 if audioPlayer.playing {             audioPlayer.pause()         } else {             audioPlayer.play()         }             }     } 
Read More

Thursday, March 10, 2016

Depth Page transform on iOS

Leave a Comment

I am trying to create a animation like of Facebook Menu Slide Down Animation of POP framework or exactly like of InShorts App. Android Documentation covers this..But cannot find any hint in iOS.

What i tried was to transform the cell as

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {      UIView.animateWithDuration(0.1, animations: { () -> Void in         cell.transform = CGAffineTransformMakeScale(0.8, 0.8)     })  } 

But this doesnot works as expected..Googling i found this one exactly what i want to acheive.But its on UIView..I think Its best fit if we animate in UITableViewCell? .I would really appreciate someone willing to help this problem.Here is the starter project i am working on

5 Answers

Answers 1

Update

Based on your video I sorted out what kind of animation you want to do. So my approach this time

  1. Work with 3 views references, which are previous, current and next.
  2. Add pan gesture to the view which is holding these views (currently self.view), and implement the 3 states of pan touch
  3. Apply transition based on gesture records, and arrange the views
  4. Some credits go to this library on GitHub, which really helped me a lot.

Code

This code has simple views, which change their background corresponding to the number of colors that we have on color array. So in your case you can create your custom XIB View, and also instead of colors you can add your own datasource. :)

import UIKit  class StackedViewController: UIViewController {     var previousView: UIView! = nil     var currentView: UIView! = nil     var nextView: UIView! = nil     var currentIndex = 0      let colors: [UIColor] = [.redColor(), .greenColor(), .yellowColor(), .grayColor()]     var offset: CGFloat = CGFloat()      // MARK: - View lifecycle      override func viewDidLoad() {         super.viewDidLoad()          // Set the offset         offset = 64.0          setupViews()     }      // MARK: - Setups      func setupViews() {         self.view.backgroundColor = .blackColor()          self.currentView = getCurrentView()         self.view.addSubview(currentView)          let pan = UIPanGestureRecognizer(target: self, action: "panAction:")         self.view.addGestureRecognizer(pan)     }      // MARK: - Actions      func panAction(gesture:UIPanGestureRecognizer){         let p = gesture.translationInView(self.view)          // Edge cases to disable panning when the view stack is finished         if p.y < 0 && getPreviousView() == nil || p.y > 0 && getNextView() == nil {             return         }          if gesture.state == .Began {             if let prev = getPreviousView() {                 self.previousView = prev                 self.view.addSubview(prev)                 prev.frame = self.view.frame                 prev.center = CGPointMake(self.view.bounds.width/2, self.view.bounds.height/2)                 self.view.sendSubviewToBack(previousView)             }              if let next = getNextView() {                 self.nextView = next                 self.view.addSubview(next)                 next.frame = CGRect(origin: CGPoint(x: 0, y: -self.view.bounds.height), size: self.view.frame.size)             }         } else if gesture.state == .Changed {             UIView.animateWithDuration(0.1, animations: { () -> Void in                 if p.y < 0 {                     self.previousView.hidden = false                     self.currentView.center.y = self.view.bounds.height/2 + p.y                     self.previousView.center.y = self.view.bounds.height/2                      // Transforming ratio from 0-1 to 0.9-1                     let ratio = (-p.y/CGRectGetHeight(self.view.bounds))                     let lightRatio = 0.9 + (ratio/10)                      // Apply transformation                     self.apply3DDepthTransform(self.previousView, ratio: lightRatio)                 } else if p.y > 0 {                     self.currentView.center.y = self.view.bounds.height/2                     let prevPosY = -self.view.bounds.height/2 + p.y                     if prevPosY < self.view.bounds.height/2 {                         self.nextView?.center.y = prevPosY                     } else {                         self.nextView?.center.y = self.view.bounds.height/2                     }                      // Transforming ratio from 0-1 to 0.9-1                     let ratio = p.y/CGRectGetHeight(self.view.bounds)                     let lightRatio = 1 - (ratio/10)                      // Apply transformation                     self.apply3DDepthTransform(self.currentView, ratio: lightRatio)                      // Hide the background view when showing another because the edges of this will be shown due to transformation                     if self.previousView != nil {                         self.previousView.hidden = true                     }                 }             })          } else if gesture.state == .Ended {             UIView.animateWithDuration(0.5, delay: 0,                 options: [.CurveEaseOut], animations: { () -> Void in                      if p.y < -self.offset && self.previousView != nil {                         // Showing previous item                         self.currentView.center.y = -self.view.bounds.height/2                          // Finish the whole transition                         self.apply3DDepthTransform(self.previousView, ratio: 1)                     } else if p.y > self.offset && self.nextView != nil {                         // Showing next item                         self.nextView?.center.y = self.view.bounds.height/2                          // Finish the whole transition                         self.apply3DDepthTransform(self.currentView, ratio: 0.9)                     } else {                         // The pan has not passed offset so just return to the main coordinates                         self.previousView?.center.y = -self.view.bounds.height/2                         self.currentView.center.y = self.view.bounds.height/2                     }                 }, completion: { (_) -> Void in                     if p.y < -self.offset && self.previousView != nil {                         self.currentView = self.getPreviousView()                         self.currentIndex = (self.currentIndex > 0) ? self.currentIndex - 1 : self.currentIndex;                     } else if p.y > self.offset && self.nextView != nil {                         self.currentView = self.getNextView()                         self.currentIndex = (self.currentIndex == self.colors.count - 1) ? self.currentIndex : self.currentIndex + 1;                     }                      // Remove all views and show the currentView                     for view in self.view.subviews {                         view.removeFromSuperview()                     }                      self.previousView = nil                     self.nextView = nil                      self.view.addSubview(self.currentView)                     self.currentView.center = CGPointMake(self.view.bounds.width/2, self.view.bounds.height/2)             })         }     }      // MARK: - Helpers      func getCurrentView() -> UIView? {         let current = UIView(frame: self.view.frame)         current.backgroundColor = colors[currentIndex]          return current     }      func getNextView() -> UIView? {         if currentIndex >= colors.count - 1 {             return nil         }         let next = UIView(frame: self.view.frame)         next.backgroundColor = colors[currentIndex + 1]          return next     }      func getPreviousView() -> UIView? {         if currentIndex <= 0 {             return nil         }         let prev = UIView(frame: self.view.frame)         prev.backgroundColor = colors[currentIndex - 1]          return prev     }      // MARK: Animation      func apply3DDepthTransform(view: UIView, ratio: CGFloat) {         view.layer.transform = CATransform3DMakeScale(ratio, ratio, ratio)         view.alpha = 1 - ((1 - ratio)*10)     } } 

Output

enter image description here

Original Answer

You can do it only with need of the cells, without having to make custom transition with UIViewController

Solution

Solution consists on:

  1. Keeping track of 2 cells, the one which is the presenter (presenterCell), and the one which is going to be presented (isBeingPresentedCell)
  2. Implement scrollViewDidScroll: which coordinates the whole operation, because everything is dependent on scrollingOffset
  3. Handle the direction of the scroll to choose which cell is the presenter and which one is being presented
  4. Everytime that a cell will be dequeued it will be set an identity transformation because on normal screen we have just one cell shown
  5. Keep ratio factor of the rect that is covering the whole frame, in order to apply the correct factor at the transformation
  6. **** You have some problems with the Autolayout on the ViewController. Please clear existing constraints, fill the view with the tableView and then let it be 0px from the Top (Not Top Layout Guide).

Code

No more talking, code talks itself (it is also some commented)

import UIKit  enum ViewControllerScrollDirection: Int {     case Up     case Down     case None }  class ViewController: UIViewController {     @IBOutlet weak var menuTableView: UITableView!     var colors :[UIColor] = [UIColor.greenColor(),UIColor.grayColor(),UIColor.purpleColor(),UIColor.redColor()]     var presenterCell: UITableViewCell! = nil     var isBeingPresentedCell: UITableViewCell! = nil     var lastContentOffset: CGFloat = CGFloat()     var scrollDirection: ViewControllerScrollDirection = .None      // MARK: - View Lifecycle      override func viewDidLoad() {         super.viewDidLoad()         // Do any additional setup after loading the view, typically from a nib.         menuTableView.dataSource = self         menuTableView.delegate = self         menuTableView.pagingEnabled = true     } }  extension ViewController:UITableViewDataSource,UITableViewDelegate {      // MARK: - Delegation      // MARK: TableView Datasource      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {         return 4     }      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {         let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell         cell.contentView.backgroundColor = colors[indexPath.row]         cell.backgroundColor = UIColor.blackColor()         cell.contentView.layer.transform = CATransform3DIdentity         cell.selectionStyle = .None          return cell     }      // MARK: TableView Delegate      func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {         return self.view.frame.size.height     }      // MARK: ScrollView Delegate      func scrollViewDidScroll(scrollView: UIScrollView) {         self.scrollDirection = getScrollDirection(scrollView)          // The cells in visible cells are ordered, so depending on scroll we set the one that we want to present         if self.scrollDirection == .Up {             self.presenterCell = menuTableView.visibleCells.last             self.isBeingPresentedCell = menuTableView.visibleCells.first         } else {             self.presenterCell = menuTableView.visibleCells.first             self.isBeingPresentedCell = menuTableView.visibleCells.last         }          // If we have the same cells or either of them is nil don't do anything         if (self.isBeingPresentedCell == nil || self.presenterCell == nil) {             return;         } else if (self.isBeingPresentedCell == self.presenterCell) {             return;         }          // Always animate the presenter cell to the identity (fixes the problem when changing direction on pan gesture)         UIView.animateWithDuration(0.1, animations: { () -> Void in             self.presenterCell.contentView.layer.transform = CATransform3DIdentity;         })          // Get the indexPath         guard let indexPath = menuTableView.indexPathForCell(presenterCell) else {             return;         }          // Get the frame for that indexPath         let frame = menuTableView.rectForRowAtIndexPath(indexPath)          // Find how much vertical space is the isBeingPresented cell using on the frame and return always the positive value         var diffY = frame.origin.y - self.lastContentOffset         diffY = (diffY > 0) ? diffY : -diffY          // Find the ratio from 0-1 which corresponds on transformation from 0.8-1         var ratio = CGFloat(diffY/CGRectGetHeight(self.menuTableView.frame))         ratio = 0.8 + (ratio/5)          // Make the animation         UIView.animateWithDuration(0.1, animations: { () -> Void in             self.isBeingPresentedCell.contentView.layer.transform = CATransform3DMakeScale(ratio, ratio, ratio)         })     }      // MARK: - Helpers      func getScrollDirection(scrollView: UIScrollView) -> ViewControllerScrollDirection {         let scrollDirection = (self.lastContentOffset > scrollView.contentOffset.y) ? ViewControllerScrollDirection.Down : ViewControllerScrollDirection.Up         self.lastContentOffset = scrollView.contentOffset.y;          return scrollDirection     } } 

UI Fix

enter image description here

Output animation

enter image description here

Hope it will fill your requirements :)

Answers 2

if you want exactly what the InShorts video is doing i'd recommend using view controller transitions. a helpful article is here.

full example code of what you are trying to achieve is below. i implemented it all in the app delegate for brevity, but you should definitely break it out into separate classes.

Video: here

UPDATED CODE

import UIKit  @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate, UIViewControllerAnimatedTransitioning {      var window: UIWindow?      var percentManager: UIPercentDrivenInteractiveTransition?      /**      Keep track of which way the animation is going      */     var isPopping = false      /**      The index of the view controller that is currently presented.      */     var index: Int {         get {             return viewControllers.indexOf(navController.viewControllers.last!)!         }     }      /**      Array of view controllers; acting as the data source      */     lazy var viewControllers: [UIViewController] = {         var viewControllers = [UIViewController]()         for i in Range(start: 0, end: 5) {             let viewController = UIViewController()             viewController.view.backgroundColor = UIColor(red: CGFloat((arc4random()%255))/255.0, green: CGFloat((arc4random()%255))/255.0, blue: CGFloat((arc4random()%255))/255.0, alpha: 1)             viewController.view.layer.cornerRadius = 12             viewControllers.append(viewController)         }          return viewControllers     }()      lazy var navController: UINavigationController = {          // create a navigation controller and hide it's nav bar         let navController = UINavigationController()         navController.navigationBar.hidden = true          return navController     }()      func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {         // add the nav controller (and it's first view controller) to the window         window = UIWindow(frame: UIScreen.mainScreen().bounds)         window?.rootViewController = navController         window?.makeKeyAndVisible()          // add the first view controller         navController.viewControllers = [viewControllers[0]]          // add a pan recognizer to the nav controller         let panRecognizer = UIPanGestureRecognizer(target: self, action: Selector("didPan:"))         navController.view.addGestureRecognizer(panRecognizer)         navController.delegate = self          return true     }      internal func didPan(recognizer: UIPanGestureRecognizer) {         guard let view = recognizer.view else { assertionFailure("no view"); return }          switch (recognizer.state) {         case .Began:             // detect if it is an upward swipe             if recognizer.velocityInView(view).y < 0 {                 // don't go out of bounds                 guard index + 1 < viewControllers.count else { recognizer.enabled = false; recognizer.enabled = true; return }                  isPopping = false                  // create the percentManager and start pushing the next view controller                 percentManager = UIPercentDrivenInteractiveTransition()                 navController.pushViewController(viewControllers[index+1], animated: true)             }             // detect if it is a downward swipe             else if recognizer.velocityInView(view).y > 0 {                 // don't go out of bounds                 guard index - 1 >= 0 else { recognizer.enabled = false; recognizer.enabled = true; return }                  isPopping = true                  // create the percentManager and start popping the current view controller                 percentManager = UIPercentDrivenInteractiveTransition()                 navController.popViewControllerAnimated(true)             }         case .Changed:             // update the percent manager             let translation = recognizer.translationInView(view)             let percentOffset = translation.y/CGRectGetHeight(view.bounds) * (isPopping ? 1 : -1)             percentManager?.updateInteractiveTransition(percentOffset)         case .Ended:              // give the percent manager it's final instruction before niling it             if isPopping {                 if recognizer.velocityInView(view).y > 0 {                     percentManager?.finishInteractiveTransition()                 } else {                     percentManager?.cancelInteractiveTransition()                 }             } else {                 if recognizer.velocityInView(view).y < 0 {                     percentManager?.finishInteractiveTransition()                 } else {                     percentManager?.cancelInteractiveTransition()                 }             }             percentManager = nil         default:             break         }     }      // MARK: UINavigationControllerDelegate      func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {         return percentManager     }      func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {         return self     }       // MARK: UIViewControllerAnimatedTransitioning      func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {         return 0.4     }      func animateTransition(transitionContext: UIViewControllerContextTransitioning) {         guard let newVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else { assertionFailure("no new view controller"); return }         guard let oldVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else { assertionFailure("no existing view controller"); return }          let scaleTransform = CGAffineTransformMakeScale(0.9, 0.9)         let yOffsetTransform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(oldVC.view.frame))          let animationBlock: Void -> Void         if isPopping {             // place the previous vc at the top of the screen             newVC.view.transform = yOffsetTransform              animationBlock = {                 oldVC.view.transform = scaleTransform                 newVC.view.transform = CGAffineTransformIdentity             }              // add the views onto the transition view controller             transitionContext.containerView()?.addSubview(oldVC.view)             transitionContext.containerView()?.addSubview(newVC.view)         } else {              // scale the new view a bit smaller             newVC.view.transform = scaleTransform              // slide the old view controller up and scale the new view controller back to 100%             animationBlock = {                 oldVC.view.transform = yOffsetTransform                 newVC.view.transform = CGAffineTransformIdentity             }              // add the views onto the transition view controller             transitionContext.containerView()?.addSubview(newVC.view)             transitionContext.containerView()?.addSubview(oldVC.view)         }          // perform the animation         UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: animationBlock, completion: { finished in             // cleanup             oldVC.view.transform = CGAffineTransformIdentity             newVC.view.transform = CGAffineTransformIdentity             transitionContext.completeTransition(!transitionContext.transitionWasCancelled())         })     } } 

Answers 3

Use facebook POP animation For drop dragged view to resting with animation

private func resetViewPositionAndTransformations() {              let resetPositionAnimation = POPSpringAnimation(propertyNamed: kPOPLayerTranslationXY)     resetPositionAnimation.fromValue = NSValue(CGPoint: CGPoint(x: dragDistance.x, y: dragDistance.y))     resetPositionAnimation.toValue = NSValue(CGPoint: CGPointZero)     resetPositionAnimation.springBounciness = cardResetAnimationSpringBounciness     resetPositionAnimation.springSpeed = cardResetAnimationSpringSpeed     resetPositionAnimation.completionBlock = {         (_, _) in         self.layer.transform = CATransform3DIdentity     }      layer.pop_addAnimation(resetPositionAnimation, forKey: "resetPositionAnimation")      let resetRotationAnimation = POPBasicAnimation(propertyNamed: kPOPLayerRotation)     resetRotationAnimation.fromValue = POPLayerGetRotationZ(layer)     resetRotationAnimation.toValue = CGFloat(0.0)     resetRotationAnimation.duration = cardResetAnimationDuration      layer.pop_addAnimation(resetRotationAnimation, forKey: "resetRotationAnimation")      let overlayAlphaAnimation = POPBasicAnimation(propertyNamed: kPOPViewAlpha)     overlayAlphaAnimation.toValue = 0.0     overlayAlphaAnimation.duration = cardResetAnimationDuration     overlayAlphaAnimation.completionBlock = { _, _ in     }     overlayView?.pop_addAnimation(overlayAlphaAnimation, forKey: "resetOverlayAnimation")      let resetScaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)     resetScaleAnimation.toValue = NSValue(CGPoint: CGPoint(x: 1.0, y: 1.0))     resetScaleAnimation.duration = cardResetAnimationDuration     layer.pop_addAnimation(resetScaleAnimation, forKey: "resetScaleAnimation") } 

Answers 4

in my opinion UICollectionview and UICollectionViewLayout is better suited for such things. UITableView don't give you per scroll transforms and you would need to do all kinds dirty hacks.

If you go with UICollectionview, what you looking for is -[UICollectionViewLayout layoutAttributesForElementsInRect:] and -[UICollectionViewLayout shouldInvalidateLayoutForBoundsChange:], everything else is a bit of math.

Answers 5

Try this: You can us facebook/pop https://github.com/facebook/pop for smoother effect. This code is just to give you some idea, not tested much.

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {     return 4 }  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {     let cell = tableView.dequeueReusableCellWithIdentifier("cell")     if cell?.contentView.viewWithTag(100) == nil     {         let view = UIView(frame: (cell?.contentView.bounds)!)          view.tag = 100         view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]         cell?.contentView.addSubview(view)     }     if cell!.contentView.viewWithTag(100) != nil     {         let view = cell!.contentView.viewWithTag(100)         view!.backgroundColor = colors[indexPath.row]     }      return cell! }  func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {     return self.view.frame.size.height - 20 }  func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {      if cell.contentView.viewWithTag(100) != nil     {         let view = cell.contentView.viewWithTag(100)         let basicAnimation = CABasicAnimation(keyPath: "transform.scale")         basicAnimation.toValue = NSNumber(float: 1)         basicAnimation.fromValue = NSNumber(float: 0.8)         basicAnimation.duration = 0.4         basicAnimation.removedOnCompletion = false         view!.layer.addAnimation(basicAnimation, forKey: "transform.scale")     }  //        if tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row - 1, inSection: 0)) != nil //        { //            let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row - 1, inSection: 0)) //            if cell!.contentView.viewWithTag(100) != nil //            { //                let view = cell!.contentView.viewWithTag(100) //                let basicAnimation = CABasicAnimation(keyPath: "transform.scale") //                basicAnimation.toValue = NSNumber(float: 0.8) //                basicAnimation.fromValue = NSNumber(float: 1) //                basicAnimation.duration = 0.4 //                basicAnimation.removedOnCompletion = false //                view!.layer.addAnimation(basicAnimation, forKey: "transform.scale") //            } //        } //        if tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row + 1, inSection: 0)) != nil //        { //            let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row + 1, inSection: 0)) //             //            if cell!.contentView.viewWithTag(100) != nil //            { //                let view = cell!.contentView.viewWithTag(100) //                let basicAnimation = CABasicAnimation(keyPath: "transform.scale") //                basicAnimation.toValue = NSNumber(float: 0.8) //                basicAnimation.fromValue = NSNumber(float: 1) //                basicAnimation.duration = 0.4 //                basicAnimation.removedOnCompletion = false //                view!.layer.addAnimation(basicAnimation, forKey: "transform.scale") //            } //        } //        let scaleAnimation = POPDecayAnimation(propertyNamed: kPOPLayerScaleXY) //        scaleAnimation.fromValue = NSValue(CGSize: CGSize(width: 0.8, height: 0.8)) //        scaleAnimation.toValue = NSValue(CGSize: CGSize(width: 1, height: 1))  //        cell.contentView.layer.pop_addAnimation(scaleAnimation, forKey: "kPOPLayerScaleXY")  //        UIView.animateWithDuration(0.1, animations: { () -> Void in //            cell.transform = CGAffineTransformMakeScale(0.8, 0.8) //        })   } 
Read More