Remove Scroll View and everything in it from the view - ios

I have a Scroll View which contains a UIImageView and an ActivityIndicator. I would like to programmatically remove the Scroll View from the view, including everything inside it. I have tried doing scrollView.removeFromSuperview() (where scrollView is an IBOutlet to the storyboard Scroll View), but I continue to get unexpectedly found nil while unwrapping an Optional value.

You should check your outlet on storyboard, I think you forgot binding your outlets with your code.

I suppose you marked your UIScrollView with ! as not optional.
Make you outlet optional, it should be like:
#IBOutlet weak var scrollView: UIScrollView?
and call removeFromSuperview() on it, like: self.scrollView?.removeFromSuperview()

Related

UIActivityIndicatorView in the same hierarchy of UITableView in UITableViewController

I have a UIViewController and I dropped a UITableView and UIActivityIndicatorView in the same hierarchy and it's working fine.
But then I have a UITableViewController, with a UITableView of course, and I try to drop a UIActivityIndicatorView at the same hierarchy as the Table View but with no luck. I know that there's a problem with UITableViewController and UIViewController with Table View but how to solve?
These two screenshots will help to understand the problem.
The way I want it to be:
The way it turns out:
The problem is that with the UIViewController it has a self.view as the root view where you can add any sub-items as you did , put you can't do this at least in IB with UITableViewController as the root view is the table itself
First way
add it in code and control is position as the tableView scrolls so change it's frame in scrollViewDidScroll so it's stay at center of screen during the loading
Second way
add it to the main window of the app and remove it when loading finishes
Ok, guys I found one more solution.
Define a variable inside UITableViewController
weak var spinner: UIActivityIndicatorView!
then in viewDidLoad method make this (hope the code is self explanatory)
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
tableView.backgroundView = activityIndicatorView
tableView.separatorStyle = .none
self.spinner = activityIndicatorView
and then call spinner.startAnimating() when you need to show it, and
self.spinner.stopAnimating()
self.tableView.separatorStyle = .singleLine
to remove it when you don't need it.
When you drag and drop any view (no matter if it is UILabel or UIActivityIndicatorView or UIView),
if it is above the cell you put there, it will be treated as the TableViewHeader automatically.
if it is below the cell you put there, it will be treated as the TableViewFooter automatically.
That is the reason why they are at the same level of view hierarchy of cells.
If you really want to use the indicatorView at same level as your tableView in your tableViewController, even if you programmatically create it and add it to your tableviewcontroller's self.view, it WILL NOT work, because tableViewController's self.view is its content view, which is scrollable anyways, which is kinda a bummer. We only have full control in UIViewController.

Can't get access to custom UIView property

I have UIView subclass
class GraphView: UIView {
var test = false
}
And when I'm trying to get access to the test property via #IBOutlet, I get exc_bad_access error.
What is my problem?
The reason can be, you are trying to access the property of the #IBOutlet before the view has loaded.#IBOutlet is initialised only when view containing the outlet is loaded.
I just had this issue. It turned out the viewController's view was connected to the IBOutlet, instead of my custom view

Attaching UIButton on top of UIScrollView or UITableView

What is the best approach for attaching a UIButton on top of UIScrollView or UITableView so when the view is scrolled, the button stays in its place.
Here examples below:
UIButton stays in the right bottom corner when the view is scrolled.
google+ app example
yahoo mail app example
I think this should work. Lay Out your button in a view that is outside of the tableviewcontroller. Then drag an outlet to the tableviewcontroller file. Then add it in code. This code would hold it at the top of the screen.
#IBOutlet var buttonView: UIView!
override func viewDidLayoutSubviews() {
self.view.addSubview(buttonView)
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
var rect = self.buttonView.frame
rect.origin.y = max(0,scrollView.contentOffset.y + scrollView.contentInset.top)
self.buttonView.frame = rect
}
Thank you all for great answers!
I got it worked through storyboard by moving the button from scrollView to View itself. That way it's attached on UIView and it's independent of scrollview.
storyboard snapshot
So now the structure is:
- View
- ScrollView
- Button
Before it was:
- View
- ScrollView
- Button
There are many ways to go about doing this but two that I use most often are as follows.
One approach is embedding the view controller within a navigation controller. This will set a bar on the top and bottom if you choose that you can place bar button items upon.
Another approach is to place a UIView along the top and snap the constraints to the left, right, and top with 0 no-margin. Then set the height. I usually use 40px for the height but you can use what is applicable to your needs. After that you can place a button in that UIView and then set constraints on it to keep in in place.
In my experience, this isn't reliably possible to do with the scrollView itself.
My solution is usually to put anything that needs to float above the tableView/scrollView in a plain ViewController that also contains the tableView/scrollView parent.
If you're using storyboards with a UITableViewController scene, this will likely mean you need to use another scene with UIViewController with a container that has your UITableViewController.
For UITableView use tableHeaderView. For UIScrollView you need to create a separate view not in the scroll view's hierarchy.
Another solution is to put your UIButton in a UIToolbar, and then make the toolbar a child of the UINavigationController's view. After that, in viewDidLayoutSubviews, you can set the rect of the toolbar to sit just below the navigation bar and offset the top of the UIScrollView or UITableView.
Add button which you want in the storyboard.
Design your scrollview
self.view.sendSubviewToBack(scrollViewObj)(in the code)
This worked for me.

Swift - Scroll a UIScrollView by tapping button inside a ViewController inside the ScrollView

I have a UIScrollView that contains a bunch of view controllers, and in each view controller there is a button that if pressed, should scroll the UIScrollView to a certain position. How do I go about connecting the viewController IBAction for the button to set the scroll position of the UIScrollView?
I know I'll call contentOffset at some point, but I'm struggling with getting the ViewControllers to control the Scroll View.
One way you could do it... When you add each UIViewController.view to the UIScrollView you could also set a var in each UIViewController that references the UIScrollView.
For example, for some UIViewController, we'll call it X, put
var scrollView: UIScrollView?
in it. Then in your class that controls the UIScrollView, when you add view X to the UIScrollView, also do the following:
viewControllerX.scrollView = self.theScrollView
Now, when your IBAction method is called in viewControllerX, you have a reference to the UIScrollView and as you said, can do self.scrollView.contentOffset.y = someValueHere to change its position.

Swift: inputAccessoryView show blank white screen for UIToolbar when called

I'm trying to add UIToolbar to my keyboard with inputAccessoryView, but once the user tap the UITextField I get an Blank white screen or load White view if i put it in viewDidLoad(). I have tried few stackoverflow QA and non of them seems to be working for me. I'm also doing this with removeFromSuperview() method.
Initialization:
#IBOutlet var MessegeView: UIToolbar!
#IBOutlet var MessegeTextField: UITextField!
Assign UIToolbar to UITextField: This code result in blank white view when it get loaded.
override func viewDidLoad() {
super.viewDidLoad()
MessegeTextField.inputAccessoryView = MessegeView
MessegeView.removeFromSuperview()
}
WITHOUT removeFromSuperView(): I get the following error and that make sense kind of.
ERROR:
should have parent view controller:<APPNAME.ChatViewController:XXXXXXXX> but requested parent is:<UIInputWindowController: XXXXXXXXXX>
A few Stackoverflow QA I follow (but no result):
Error when adding input view to textfield iOS 8
Leaving inputAccessoryView visible after keyboard is dismissed iOS8?
How views are setup:
If you setup your UI in a Storyboard then you don't own the objects and shouldn't alter the hierarchy. That's why Xcode auto-generated properties from storyboards are #IBOutlet weak var by default, you don't own them and shouldn't manage the memory.
To fix your problem you should either use var MessegeView = UIToolbar() or you should initialize the toolbar from a separate .xib.

Resources