I have created a custom UIView and have a protocol set for it. Now from the View Controller when I set the delegate to self I am getting an EXC_BAD_ACCESS.
---The View Controller Code------
class VerificationController: UIViewController, LoadingViewDelegate {
#IBOutlet weak var instructionView: LoadingView!
override func viewDidLoad() {
super.viewDidLoad()
instructionView.randomTextIndexes = [1]
instructionView.delegate = self
}
...
}
// "instructionView" is the UIView outlet and "LoadingView" is the class
--This is the custom View Code ------
protocol LoadingViewDelegate {
func generated(random code:String)
}
class LoadingView: UIView {
var delegate:LoadingViewDelegate?
var randomTextIndexes:[Int] = []
}
I am getting EXC_BAD_ACCESS when I try to access the delegate as well as the randomTextIndexes from the viewDidLoad() method of the view controller. Could you please tell me what I am missing here.
My best guess is that you forgot to set the class of the custom view in the Interface Builder. Check the Identity Inspector for your object in the IB, it should look like this:
If it isn't set, then that's the problem.
Related
I am creating a screen like below:
But the problem is, pagedView requires my view controller to inherit from UIPagedViewController, while colleciton view requires inheriting from UICollectionViewController.
Is there a way to achieve this?
You don't have to use UIPagedViewController or UICollectionViewController make it inherit from UIViewController , and inside say loadView/ViewDidLoad use
let pager = UIPagedViewController()
// then add it as a child vc and constraint it's view or set a frame
and
let collec = UICollectionView(///
// add to view and constraint also
The above should be instance vars also , so their delegates/dataSources being retained
what about like this?
class MyPagedView: UIView, UIPageViewControllerDataSource {
// add your pages
}
class MyCollectionView: UICollectionView, UICollectionViewDataSource {
// add your collection view
}
class ViewController: UIViewController {
lazy var myPages: MyPagedView = {
let pages = MyPagedView()
return pages
}()
lazy var myCV: MyCollectionView = {
let cv = MyCollectionView()
return cv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(myPages)
view.addSubview(myCV)
}
}
Of Course, you will have to set your constraints according to your need.
base ViewController
import UIKit
class SubViewPost: UIViewController {
#IBOutlet weak var content: UILabel!
#IBOutlet weak var recommendCount: UILabel!
#IBOutlet weak var recommendButton: UIButton!
var postInfo:PostInfo!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
child ViewController
import UIKit
class SubViewOne: SubViewPost {
#IBAction func likeWorry(_ sender: Any) {
Option.recommend(postInfo: postInfo, mRecommendCount: recommendCount, mRecommendButton: recommendButton)
}
}
and another child viewController
import UIKit
class SubViewTwo: SubViewPost {
override func viewDidLoad() {
recommendCount.alpha=0
recommendButton.alpha=0
}
}
i want add subviewOne or SubViewTwo
My ParentView
var subViewPost:SubViewPost
if postType == 1{
subViewPost = storyboard?.instantiateViewController(withIdentifier: "SubViewPost") as! SubViewOne
}else{
subViewPost = storyboard?.instantiateViewController(withIdentifier: "SubViewPost") as! SubViewTwo
}
containerView.addSubview(subViewPost.view)
raise error
Could not cast value of type
'MyApp.SubViewPost' (0x101151728) to 'MyApp.SubViewOne' (0x10114d9d0).
2018-07-10 14:40:56.007436+0900 MyApp[7207:209932]
Could not cast value of type 'MyApp.SubViewPost' (0x101151728) to 'MyApp.SubViewOne' (0x10114d9d0).
how to chagne view controller by According to postType
SubView One have Recommned
but SubView Two haven't Recommend
SubView 1,2 have same UI
The UViewController class for your scene "SubViewPost" in your storyboard is set to SubViewPost and that is what instantiateViewController will be returning. You cannot downcast an instance of SubViewPost to SubViewOne or SubViewTwo.
You could define two identical scenes in your storyboard, each with the appropriate view controller class, but that would require a lot of duplication.
Since the only difference is the visibility of the recommendButton and recommendCount elements, why not just handle that via a property:
var subViewPost = storyboard?.instantiateViewController(withIdentifier: "SubViewPost") as! SubViewPost
subViewPost.recommendVisible = (postType == 1)
SubViewPost.swift
var recommendVisible = true
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
recommendCount.isHidden = !recommendVisible
recommendButton.isHidden = !recommendVisible
}
The error message is clear. When you say
storyboard?.instantiateViewController(withIdentifier: "SubViewPost")
what you get from the storyboard is a view controller whose class is SubViewPost. You cannot wave a magic casting wand and claim that it is a SubViewOne instead; it isn't.
If you wanted this view controller to be a SubViewOne, then you should have declared it as a SubViewOne in the storyboard in the Identity inspector.
I think I see what you are trying to do, and why you are confused about why you can't do it this way.
What's in the storyboard is an instance, not a class. Yes, it is an instance of some class, but it is an instance of that class. So when you design the interface in the storyboard, you are designing the interface associated with that one instance of that one class.
If your goal is to have a single interface associated with multiple classes, the interface must be generated in code or loaded from a View .xib file — not designed in a storyboard.
However, you would be better off not trying to use subclassing in this situation in the first place. What I do in a similar situation is give my view controller an enum property that says which "kind" of view controller it is, and obey accordingly in code. That a way, a single class serves multiple purposes.
I subclassed UIImageView to add a custom property.
class ProfilePictureImageView: UIImageView {
var isAffirmed: Bool?
}
When trying to set isAffirmed, I get an EXC_BAD_ACCESS error. Here is a stripped down version of my class to show the error:
class SettingsTableViewController: UITableViewController {
#IBOutlet weak var userImageView: ProfilePictureImageView!
override func viewDidLoad() {
super.viewDidLoad()
userImageView.image = nil // This works
userImageView.isAffirmed = true //EXC_BAD_ACCESS error here
}
}
I'm able to access and set properties of UIImageView (such as image), but not properties from my subclass. What is the cause of this error?
Make sure that you have set the custom class for the UIImageView in your storyboard, otherwise you will get a plain old UIImageView and an exception when you access the new property
Sounds like you haven't changed your class from UIImageView to ProfilePictureImageView in Interface Builder.
I have an UIViewController
class WelcomeViewController: UIViewController
and an UIView
class SignUpView: UIView
Now I want to set in my WelcomeViewController delegate of SignUpView:
protocol SegueDelegate {
func runSegue(identifier: String)
}
class SignUpView: UIView { ... }
and connect it in
class WelcomeViewController: UIViewController, SegueDelegate {
how can I set in my WelcomeViiewController those delegate? When I'm trying to set:
override func viewDidLoad() {
SignUpView.delegate = self
}
it returns me
Instance member 'delegate' cannot be used on type 'SignUpView'
how can I find a solution?
You are trying to set delegate to a class. It should be an instance of the class i.e
let signUpView = SignUpView()
signUpView.delegate = self
What would be the point in doing that? If you want to navigate from one View to another, just add that Segue in Storyboard with an Identifier, so you can call self.performSegueWithIdentifier("IdentifierOfSegue", sender: self)
Create a weak property in SignUpView of that delegate(protocol) and name it other than delegate
then you can set and use it.
I agree with the developers saying "you can just do that via segue" but
the problem is you didn't declare a delegate var in the SignUpView class
so you can implement it in the signIn , if you declared it please write the line of code for me in a comment to check it
for now ...
I can suggest that you make a subview to be a parent class then override
which method you want to call
and you need to declare the delegate var as an optional (so you won't have
a memory cycle) like the following line ...
var delegate: SegueDelegate?
Let's solve this for people in need whom could need a solution when reading this issue:
In your UIView:
class SignUpView: UIView
you need to add:
var delegate : SegueDelegate?
Now, still in your class SignUpView, you need to add the function you want to delegate, just like this:
func runSegue(identifier: String) {
delegate?.runSegue(identifier)
}
This will call your delegate:
protocol SegueDelegate {
func runSegue(identifier: String)
}
Now, in your ViewController, you should have your SignUpView somewhere (created programmatically or linked through Storyboard / XIB).
In your viewDidLoadfunction, add: signUpView.delegate = self.
Don't forget to add SegueDelegatein your class heritage.
I'm trying to create a reusable UIView that I can place in multiple UIViewControllers. I gave it delegate methods that I want the parent UIViewControllers to access, but it throws me an error (commented in the code below). What's a better way I can solve this?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var cameraView: CameraView!
override func viewDidLoad() {
super.viewDidLoad()
self.cameraView.delegate = self
//ERROR: Cannot assign a value of type 'viewController' to a value of type 'CameraViewDelegate?'
}
}
protocol CameraViewDelegate {
func cameraViewShutterButtonTapped()
func cameraViewimagePickerTapped(imageData: NSData)
}
class CameraView: UIView {
var delegate:CameraViewDelegate?
//Ect...
}
You have not specified that ViewController conforms to the CameraViewDelegate protocol. You should amend your code to this:
class ViewController: UIViewController, CameraViewDelegate {
…at which point Xcode will complain that you have not implemented cameraViewShutterButtonTapped() and cameraViewimagePickerTapped(), which at least tells you that you're on the right track!
Side note: do you really want the camera view to have a strong reference to its delegate? You might want that to be weak.
You need to have your ViewController class implement the CameraViewDelegate protocol, like so:
class ViewController : UIViewController, CameraViewDelegate { ... }