Dynamic object creation in Swift 3 - ios

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")
} }

Related

Background Colour in UIView not showing

I have a UIView that should show two colours, red and orange, based on the value of rating: Double The problem is that when I run the app nothing is showing up. In my output log the function prints that it has run and that the rating value is what it should be. So I am not sure why nothing is showing up when I run the app, I just see white.
class RatingViewController: UIView {
var rating: Double = 1.0
var rate: Double? {
didSet {
rating = rate!
setUpView()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private func setUpView() {
Self.backgroundcolor = UIColor.yellow
print("rating is \(rating), and width is \((UIScreen.main.bounds.width * CGFloat(rating/10)))")
let width = (UIScreen.main.bounds.width * CGFloat(rating/10))
var view: UIView
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: self.frame.size.height))
view.backgroundColor = UIColor.red
self.addSubview(view)
}
}
You have to add setUpView in init(: method
class RatingViewController: UIView {
var rating: Double = 1.0
required init?(coder: NSCoder) {
super.init(coder: coder)
}
init(frame: CGRect, rate: Double) {
super.init(frame: frame)
self.rating = rate
setUpView()
}
private func setUpView() {
self.backgroundColor = UIColor.yellow
print("rating is \(rating), and width is \((UIScreen.main.bounds.width * CGFloat(rating/10)))")
let width = (UIScreen.main.bounds.width * CGFloat(rating/10))
var view: UIView
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: self.frame.size.height))
view.backgroundColor = UIColor.red
self.addSubview(view)
}
}
Now you can call this class with custom init method like that:
// chnage frame and rate according to your requirment
let rView = RatingViewController(frame: CGRect(x: 0, y: 0, width: 320, height: 300), rate: 2.0)

Collection Cell Content Size

I added a view as parent red view in CollectionViewCell and the next blue subview at the center of the parent view. It works correctly and the sub view goes at the center of the parent view before collection cell size is not changed. But, The cell size is changed by conforming the method from UICollectionViewDelegateFlowLayout protocol and the view is not centered of the cell correctly. How I can solve this issue ?
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
self.circularView.center = self.parentView.center
}
}
1]2
Try this code
self.circularView.center = CGPoint(x: self. parentView.bounds.midX, y: self. parentView.bounds.midY)
self.parentView.addSubview(self.circularView)
self.addSubview(parentView)
Try doing:
self.circularView.center = CGPointMake(CGRectGetMidX(self.parentView.bounds), CGRectGetMidY(self.parentView.bounds))
Why this should work? Try checking values of self.parentView.center for each cell, they might not be what you want them to be, because center property gives values with respect to parent view coordinate system.
Remove the following line from updateView()
self.circularView.center = self.parentView.center
Please add it to the following method:
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
e.g.
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
}
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
}

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")
}
}

how to declare UIView globally in swift?

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.

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