Linking text views to scroll together - ios

I have two side by side text views. How can I link them so that if one is scrolled down other automatically scrolls the same as first one in swift 2.

Set your viewController conforms to UITextViewDelegate,then set textView delegate to self,then in scrollViewDidScroll sync both contentOffSet
For example
Gif
Code
class ViewController: UIViewController,UITextViewDelegate {
#IBOutlet weak var textview2: UITextView!
#IBOutlet weak var textview1: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textview1.delegate = self
textview2.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == textview1{
textview2.contentOffset = textview1.contentOffset
}else{
textview1.contentOffset = textview2.contentOffset
}
}
}

Related

How to prevent subview release self after call removeFromSuperview?

I want to change with two subviews as button been clicked, the subview was created by StoryBoard, each subview has a button, click the button will bring another subview and hidden current one.
But I found when a subview call removeFromSuperview(), it will be release automatically, if I want to use this subview later, I need a var to point it.
Here is my code:
class ViewController: UIViewController {
#IBOutlet weak var secondView: UIView!
#IBOutlet weak var firstView: UIView!
var temp1: UIView?
var temp2: UIView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
temp1 = firstView
temp2 = secondView
secondView.removeFromSuperview()
}
#IBAction func moveToSecond(_ sender: UIButton) {
firstView.removeFromSuperview()
view.insertSubview(secondView, at: 0)
secondView.isUserInteractionEnabled = true
}
#IBAction func moveToFirst(_ sender: UIButton) {
secondView.removeFromSuperview()
view.insertSubview(firstView, at: 0)
firstView.isUserInteractionEnabled = true
}
}
Without two temp var, subview will release after removeFromSuperview, and cause next insertSubview crash because it is nil.
So, How to prevent subview auto release?
Is there another way to change between two subviews created by StoryBoard graceful?
My mistake, I didn't notice that outlet is weak, everything is reasonable, when removeFromSuperview, no strong point is left to the sub view, than it release automatically.
You can use #IBOutlet var secondView: UIView! to create strong reference of the view.But as per your requirement I suggest not to remove it from the super view. Instead of that you should hide and show the views when needed as below.
class ViewController: UIViewController {
#IBOutlet var secondView: UIView!
#IBOutlet var firstView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
secondView.isHidden = true
}
#IBAction func moveToSecond(_ sender: UIButton) {
firstView.isHidden = true
secondView.isHidden = false
secondView.isUserInteractionEnabled = true
}
#IBAction func moveToFirst(_ sender: UIButton) {
secondView.isHidden = true
firstView.isHidden = false
firstView.isUserInteractionEnabled = true
}
}
Assuming your two views are one upon above , having same width and same height . In viewDidLoad . first set the firstView to front and secondView to back. Once button click i bring secondView to front and firstView to back , like so on.
import UIKit
class ViewController1: UIViewController {
#IBOutlet var secondView: UIView!
#IBOutlet var firstView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.bringSubview(toFront: firstView)
self.view.sendSubview(toBack: secondView)
}
#IBAction func moveToSecond(_ sender: UIButton) {
self.view.bringSubview(toFront: secondView)
self.view.sendSubview(toBack: firstView)
}
#IBAction func moveToFirst(_ sender: UIButton) {
self.view.bringSubview(toFront: firstView)
self.view.sendSubview(toBack: secondView)
}
}
If your two sub view's are in different position of the view. then you need to hide alternative View in respective button click
class ViewController: UIViewController {
#IBOutlet var secondView: UIView!
#IBOutlet var firstView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
secondView.isHidden = true
firstView.isUserInteractionEnabled = true
}
#IBAction func moveToSecond(_ sender: UIButton) {
firstView.isHidden = true
secondView.isHidden = false
secondView.isUserInteractionEnabled = true
}
#IBAction func moveToFirst(_ sender: UIButton) {
secondView.isHidden = true
firstView.isHidden = false
firstView.isUserInteractionEnabled = true
}
}

Xcode 8/ Swift 3 - How can I lock button constraints to a pinch to zoom image so they zoom in and out with the image?

I have a view controller with a scroll view, followed by a map-like image inside the view. On top of the map image I have 16 different pin buttons pointing to different parts on a map image. As of now I can zoom in and out of the map but the 16 buttons do not follow and get scattered. How can I attach or lock the buttons onto the map image so they zoom in and out with the map. As of now inside my map view controller I have this: (thanks in advance for an answer!)
import UIKit
class MapppViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var mainScrollView: UIScrollView!
#IBOutlet weak var mapImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.mainScrollView.minimumZoomScale = 1.0
self.mainScrollView.maximumZoomScale = 5.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func viewForZooming(in scrollView: UIScrollView ) -> UIView?
{
return self.mapImageView
In a sketchy way, I presume this is the sort of thing you're after:
You can achieve that either by making the buttons subviews of the image view or (as I did here) by making the buttons and the image view subviews of a "container view" that serves no other purpose except to be the zoomable subview of the scroll view.
Here's my view hierarchy:
Here's the only code:
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var sv: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
self.sv.minimumZoomScale = 1
self.sv.maximumZoomScale = 2
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return scrollView.viewWithTag(999) // the container view
}
}

Container view losing textField values when a button is tapped in the parent viewController

I have a viewController with a UISegmentedControl and a UIButton.
Within this viewController, I have two containers, each containing one viewController with a UITextField inside.
I want to save the values in the textField on the click of the button.
Here's the code I have written so far:
View Controller:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//
//
containerA.showView()
containerB.hideView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(sender: UIButton) {
print(ContainerAViewController.sharedInstance.textFieldA)
}
#IBAction func segmentedControlValueChanged(sender: AnyObject) {
switch(sender.selectedSegmentIndex) {
case 0 : containerA.showView()
containerB.hideView()
case 1 : containerB.showView()
containerA.hideView()
default : containerA.showView()
containerB.hideView()
}
}
#IBOutlet weak var containerA: UIView!
#IBOutlet weak var containerB: UIView!
func hideView(view: UIView) {
view.userInteractionEnabled = false
view.hidden = true
}
func showView(view: UIView) {
view.userInteractionEnabled = true
view.hidden = false
}
}
extension UIView {
func hideView() -> UIView {
self.userInteractionEnabled = false
self.hidden = true
return self
}
func showView() -> UIView {
self.userInteractionEnabled = true
self.hidden = false
return self
}
}
ContainerAViewController:
class ContainerAViewController: UIViewController {
#IBOutlet weak var textFieldA: UITextField!
static let sharedInstance = ContainerAViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
ContainerBViewController:
class ContainerBViewController: UIViewController {
#IBOutlet weak var textFieldB: UITextField!
static let sharedInstance = ContainerBViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
When I tap the button, it gives me the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Can somebody please help?
You should not try to manipulate another view controller's views. That violates the principle of encapsulation, an important principle in object-oriented development.
You should give your child view controllers (ContainerAViewController and ContainerBViewController) string properties, and have the code for those view controllers set that string property when the user enters text into the view controllers' text fields.
Ignoring that design flaw, your code doesn't make sense. You show your CLASS as ContainerAViewController, and yet your buttonTapped method is trying to ask a ContainerAViewController singleton for the value of a text field. That makes no sense.
You want to have properties in your parent view controller that point to your child view controllers.
You should implement a prepareForSegue method in your parent view controller, and in that prepareForSegue method, look for the embed segues that fire when the child view controllers are loaded. When that happens you should set your properties that point to the child view controllers.

UIView doesn't center properly in UIScrollView with autolayout

I'm making an application where I need an x amount of custom UIView and place them in a scrollView. The layout of the scrollView and the UIView xib are set with AutoLayout. The result I'm getting now is this:
First View is well centred in ScrollView
Second View is wrong and has a lot of space in between
See my VC Code under here.
let sponsors = Sponsors.createSponsors() <-- Array
override func viewDidLoad() {
super.viewDidLoad()
configureSponsors()
}
//MARK: Load the AddView in ScrollView
func configureSponsors() {
self.scrollView.contentSize = CGSizeMake(CGFloat(sponsors.count) * self.scrollView.frame.size.width, self.scrollView.frame.size.height)
for sponsor in sponsors {
numberOfItems++
let addView = NSBundle.mainBundle().loadNibNamed("AddView", owner: self, options: nil).last as! AddView
addView.addDataToAddView(sponsor)
addView.frame = CGRectMake(CGFloat(numberOfItems - 1) * scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height)
self.scrollView.addSubview(addView)
}
}
And here is my UIView code:
//MARK: Outlets
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var sponsorTitle: UILabel!
#IBOutlet weak var sponsorLogo: UIImageView!
#IBOutlet weak var sponsorSubtitle: UILabel!
#IBOutlet weak var roundView: UIView!
#IBOutlet weak var playMusicButton: UIButton!
//MARK: Properties
var cornerRadius: CGFloat = 3.0
func addDataToAddView(sponsor: Sponsors) {
backgroundImageView.image = UIImage(named: sponsor.backgroundImage)
sponsorLogo.image = UIImage(named: sponsor.logoImage)
sponsorTitle.text = sponsor.title
sponsorSubtitle.text = sponsor.subTitle
}
override func layoutSubviews() {
roundView.layer.cornerRadius = roundView.frame.size.width / 2
roundView.alpha = 0.7
roundView.clipsToBounds = true
}
//MARK: PlayVideo
#IBAction func playVideo(sender: UIButton) {
//play music
}
I've already searched for the same problems. I found out that I have to use the Pure Auto Layout Approach. Should that mean I need to programatically set the constraints for the UIView?
Many thanks,
Dax
Update:
Pictures for scrollView setup:
You should not perform layout calculations in viewDidLoad as frames are not set correctly till then.
Correct place to do this is either viewWillLayoutSubviews or viewDidLayoutSubviews as you will get the correct frame data when these functions are called

Resizing UITextView to fit content in Swift

This is my second view called detail view and I am bringing over text from the first view into the detail view. Some of the text is larger than others, so I am trying to make it to where my textview changes automatically to adapt to the amount of text needed. I am still new to Swift so any help is appreciated.
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var symptomsTextView: UITextView!
#IBOutlet weak var stepsTextView: UITextView!
#IBOutlet weak var emergencyLabel: UILabel!
var medicalObject : MedicalInfo? = nil
var emergencyText = ""
var symptomsText = ""
var stepsText = ""
//Function to show text in labels and text views
override func viewWillAppear(animated: Bool) {
//Adding text to the labels and text views
emergencyLabel.text = emergencyText
symptomsTextView.text = symptomsText
stepsTextView.text = stepsText
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources