how to declare UIView globally in swift? - ios

Unable to create View globally. My code is :
required init(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// CODING
class ViewController: UIViewController {
//Unable to create View globally, kindly help me,,
//Error coming like this
required init(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
var view11:UIView
var img_view11:UIImageView
.
.
.
#IBAction func long(sender: UILongPressGestureRecognizer)
{
var data1: NSData = UIImagePNGRepresentation(img.image)
view11 = UIView(frame: CGRect(x: 25, y: 0, width: 300, height: 200))
img_view11 = UIImageView(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
img_view11.image = UIImage(data: data1)
view11.addSubview(img_view11)
self.vw.addSubview(view11)
}
}
If we erase that "required" line, we get this error:
"fix-it Insert \n required initializer."
after that, if we run, then the thread error is thrown.

Outside the class do:
var imageView: UIImageView = UIImageView()
Then you will be able to use it globally

You can get rid of the error by replacing the fatalError code with super.init(coder: aDecoder).
This initialization is required for objects that are initialized from a nib (or storyboard), I believe.

Related

Do I need to inject properties in both init(coder) and init(size)?

I'm trying to set property values in my SpriteKit project using a constructor (init). Since swift doesn't inherit init methods it's not always as simple as just adding a clean init() method and take it from there. My project require me to include both the init(size) and init(coder) methods. That's fine.
However, this also seem to mean that I need to inject my properties in both init methods. To me that seems a bit redundant, but the compiler forces me to do so. So, my question is, is this the way to do it, or is there a cleaner way, so I don't need to use two init methods that set the same property values? Here's what the code look like:
class GameScene: SKScene {
let myVariable: SKShapeNode
override init(size: CGSize) {
myVariable = SKShapeNode(rectOf: CGSize(width: 200, height: 200))
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
myVariable = SKShapeNode(rectOf: CGSize(width: 200, height: 200))
super.init(coder: aDecoder)
}
}
...and the class calling GameScene:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
let scene = GameScene(size: view.frame.size)
scene.scaleMode = .aspectFill
scene.size = view.frame.size
scene.anchorPoint = CGPoint(x:0 , y: 1)
view.presentScene(scene)
}
Often the coder init isn't being used (e.g., you're creating the scene only programmatically). Then you can just stub out the required coder init:
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Edit: As Ron points out, if you're using the editor to create the scene and are loading if from an SKS file, the coder init is the one that you have to implement.
You can just do it by doing by defining it in your let statement providing self is not used, or doing via lazy.
class GameScene: SKScene {
let myVariable: SKShapeNode = SKShapeNode(rectOf: CGSize(width: 200, height: 200))
override init(size: CGSize) {
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
class GameScene: SKScene {
lazy var myVariable: SKShapeNode = {
var node = SKShapeNode(rectOf: CGSize(width: 200, height: 200))
//Maybe we want to add it to the scene here
return node
}
override init(size: CGSize) {
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

Error "EXC BAD ACCESS"with subclass in Swift

I made 3 files GameViewController, GameView, GameItemView but if GameItemView inherits GameView than
EXC BAD ACCESS error appeared
like below code.
class GameViewController: UIViewController {
var gameView: GameView!
override func viewDidLoad() {
super.viewDidLoad()
gameView = GameView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.view.addSubview(gameView)
gameView.gameViewController = self
}
//....
}
class GameView: UIView {
weak var gameViewController: GameViewController! //when GameViewController will appear, BAD ACCESS error appear and stop here
weak var gameItemView: GameItemView!
override init(frame: CGRect) {
super.init(frame: frame)
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
//....
}
class GameItemView: GameView {
override init(frame: CGRect) {
super.init(frame: frame)
//add some views
}
//...
}
I wrote some code of GameItemView on GameView before. But GameView's code became so long, so I moved a part of them to GameItemView. But then the error appeared. How can I solve it?
UPDATE:
I'll add the code where I got the error. I'm sorry I forgot to write it.
var gameGameViewController: GameViewController!
Why are you inheriting GamveViewItem from GameView? If you wanted to do so then why are coding like above which causes recursive calls to the init of GamveViewItem & GameView. Please either change the parent class of the GamveViewItem to UIView or some other or break the recursive pattern caused by the init.
GameView's init
override init(frame: CGRect) {
super.init(frame: frame)
// Here you're calling GameItemView's init, now go to GameItemView's init
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
GameItemView's init
override init(frame: CGRect) {
// You're calling GameView's init here and it goes back to
// there and then this keep on happening
super.init(frame: frame)
//add some views
}
try this:
class GameViewController: UIViewController {
var gameView: GameView!
override func viewDidLoad() {
super.viewDidLoad()
gameView = GameView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.view.addSubview(gameView)
gameView.gameViewController = self
}
//....
}
class GameView: UIView {
var gameViewController = GameViewController()
var gameItemView = GameItemView()
override init(frame: CGRect) {
super.init(frame:frame)
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class GameItemView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//add some views
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

Dynamic object creation in Swift 3

I am a total swift noob. I am trying to build dynamic objects. In my example I am trying to create instances of a PAGE class from my BOOK class. I guess I am not sure how to dynamically create them/name them or reference them for use later. I understand I cannot create dynamic names... I am guessing I put them into tan array? Any help or input appreciated.
//page class
class pageview : UIView {
var page: UIView!
init () {
super.init(frame: CGRect(x: 0, y: 0, width: bookwidth, height: bookheight))
page = UIView(frame: CGRect(x: bookposx, y: bookposy, width: bookwidth, height: bookheight))
page.backgroundColor = UIColor.blue
book.addSubview(page)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//book class
class bookview : UIView {
var cover: UIView!
var backcover: UIView!
var page: UIImageView!
init (numberofpages: Int) {
super.init(frame: CGRect(x: 0, y: 0, width: bookwidth, height: bookheight))
//pages
for i in 0 ..< numberofpages {
//PROBLEM HERE
let page (i) = pageview()
self.addSubview(page (i))
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//add book
let book = bookview(numberofpages: 3)
container.addSubview(book)
I don't know if I undestand your question correctly. But check this out:
class bookview : UIView {
var cover: UIView!
var backcover: UIView!
var pages: [pageview] = []
init (numberofpages: Int) {
super.init(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
//pages
for _ in 0 ..< numberofpages {
let page = pageview()
pages.append(page)
self.addSubview(page)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
} }

Adding and changing a custom UIView programmatically (Swift)

I am trying to create a custom UIView that I can use in my other UIViewControllers.
The custom view:
import UIKit
class customView: UIView {
override init(frame: CGRect) {
super.init(frame:frame)
let myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 250, height: 100))
addSubview(myLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Then I want to add it in to a separate UIViewController:
let newView = customView(frame:CGRectMake(0, 0, 500, 400))
self.view.addSubview(newView)
This works to display the view, but what do I need to add to be able to change the properties (such as myLabel) from the UIViewController that is embedding the customView?
I'd like to be able to access and change the label from the viewController, allowing me to change text, alpha, font, or hide the label using dot notation:
newView.myLabel.text = "changed label!"
Trying to access the label now gives the error "Value of type 'customView' has no member 'myLabel'"
Thanks so much for any help!
This is because the property myLabel is not declared at the class level. Move the property declaration to class level and mark it public. Then you will be able to access it from outside.
Something like
import UIKit
class customView: UIView {
public myLabel: UILabel?
override init(frame: CGRect) {
super.init(frame:frame)
myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 250, height: 100))
addSubview(myLabel!)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

Crashed when accessing property defined in BFPaperButton subclass

I am working on creating a customized button in Swift.
When I subclassed UIButton class, it works fine.
But it crashed when I replace super class with BFPaperButton (https://github.com/bfeher/BFPaperButton)
I have fixed the init method name conversion error with:
#define initFlat initWithFlat
#define initFlatWithFrame initWithFlatWithFrame
#define initRaised initWithRaised
#define initRaisedWithFrame initWithRaisedWithFrame
Then I got EXC_BAD_ACCESS when accessing the new defined property:
(An UserCountButton Instance).countLabel.text = ...
This is my implementation:
import UIKit
class UserButton: BFPaperButton {
let footerLabel = UILabel()
override init() {
super.init(flatWithFrame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width / 3, height: 100))
addSubview(footerLabel)
layer.contentsScale = UIScreen.mainScreen().scale
footerLabel.frame = CGRect(x: 0, y: 60, width: bounds.width, height: 40)
footerLabel.textColor = UIColor.grayColor()
footerLabel.textAlignment = .Center
footerLabel.font = UIFont.systemFontOfSize(12)
}
override init(raisedWithFrame frame: CGRect) {
super.init(raisedWithFrame: frame)
}
override init(flat: ()) {
super.init(flat: ())
}
override init(flatWithFrame frame: CGRect) {
super.init(flatWithFrame: frame)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
class UserCountButton: UserButton {
let countLabel = UILabel()
override init() {
super.init()
addSubview(countLabel)
countLabel.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 90)
countLabel.textColor = UIColor.darkGrayColor()
countLabel.textAlignment = .Center
countLabel.font = UIFont.systemFontOfSize(32)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
Is that a bug or some what? How can I fix it? (I'm using Xcode 6 Beta 5)
From what I can tell, the problem is that you are trying to change stuff on your countLabel, but you have defined it via let which makes it immutable. Try changing that to var, and then setting all of it's properties.
Also, it should be noted that I believe you need to do all the subview initialization BEFORE you call addSubview, for both your UserCountButton and your UserButton.

Resources