I’m trying to reuse a component from a xib in a Swift project, but I’m using Objective C logic. Thus, subclassing a view and loading the xib, then instantiating the custom view in the view controller.
Translating the code into Swift is not producing the results expected.
CustomView.swift:
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("Error detected")
self.commonInit()
}
private func commonInit() {
NSBundle.mainBundle().loadNibNamed("mainBar", owner: self, options: nil)
self.addSubview(self)
}
viewController.swift:
var bottomBar : customView = customView(frame: CGRect(x: 0, y: 250, width: 250, height: 70))
//bottomBar.backgroundColor = UIColor.redColor()
self.view.addSubview(bottomBar)
Objective-C I used as a reference:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self baseInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"yourXib" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
CustomView * myView = [CustomView alloc]init];
[self.view addSubView:myView];
Any comment in the right direction is appreciated.
Not 100 percent sure if your OBJ-C code actually work, but most probably don't.
You have to realise that this [[NSBundle mainBundle] loadNibNamed:#"yourXib" owner:self options:nil]; returns always array of objects in your IB xib files. You actually don't assign this object anywhere as far as I see.
The problem with this implementation might be frame that can be taken from bounds.
This code works if we assume that there is only one object in an IB object.
private func commonInit()
{
var nibView = NSBundle.mainBundle().loadNibNamed("mainBar", owner: self, options: nil)[0] as UIView
nibView.frame = self.bounds;
self.addSubview(nibView)
}
You can try This
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib ()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib ()
}
func loadViewFromNib() {
let view = UINib(nibName: "CreditCardExperyView", bundle: NSBundle(forClass: self.dynamicType)).instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(view);
}
// Call subview
let creditCardView : CreditCardExperyView = CreditCardExperyView(frame: CGRect(x: 0, y: UIScreen.mainScreen().bounds.size.height - 280, width: UIScreen.mainScreen().bounds.size.width, height: 280))
selfView.addSubview(creditCardView)
Related
I am having problems with my Xib UIView.I created an xib view, added it to a uiview class, and then called this class in the main viewcontroller. In my xib view I created a label which is centered there directly in the center. Only when I start my project is the view no longer displayed in the center:
Look
But this is what my view looks like in the xib file:
Look
Could it be that it is because of the navigation controller? Although I don't think so, because I also added the navigation controller to my xib file. By the way, my custom view is added to a scrollview in my main viewcontroller.
This is my custom view class:
import UIKit
class TimerView: UIView {
#IBOutlet var contentView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private func commonInit() {
Bundle.main.loadNibNamed("TimerView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}
and there I added it to the scrollview:
func setUpScrollView() {
sequenzeScrollView.contentSize = CGSize(width: view.frame.size.width * 3, height: 0)
sequenzeScrollView.isPagingEnabled = true
sequenzeScrollView.showsVerticalScrollIndicator = false
sequenzeScrollView.showsHorizontalScrollIndicator = false
sequenzeScrollView.delegate = self
for i in 0..<3 {
let timerView = TimerView(frame: CGRect(x: view.frame.size.width * CGFloat(i), y: 0, width: view.frame.size.width, height: view.frame.size.height))
sequenzeScrollView.addSubview(timerView)
}
}
can someone help me with this? I would be really happy about that! Love greetings
I have some requirement to show popup as some customisation options.
So, I took custom view as UIView with Xib file.
class CustomAlertView : UIView {
#IBOutlet weak var customAlertView : UIView!
#IBOutlet weak var button1 : UIButton!
#IBOutlet weak var button2 : UIButton!
override init(frame: CGRect) { // for using CustomView in code
super.init(frame: frame)
self.commonInit()
}
required init?(coder aDecoder: NSCoder) { // for using CustomView in IB
super.init(coder: aDecoder)
self.commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("CustomAlertView", owner: self)
guard let content = customAlertView else { return }
content.frame = self.bounds
content.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.addSubview(content)
}
}
And given outlet connections.
And I am able to load the view in viewcontroller class.
But, the issue is, its not showing as pop up view and its not showing any border color, etc even I added too.
And the present self.view (Main view from viewcontroller) still moving it has tableview, while I clicking on the buttons on custom view, nothing happening.
func someAction() {
self.view.addSubview(customAlert)
self.customAlert.layer.cornerRadius = 13
self.customAlert.layer.borderWidth = 10
self.customAlert.layer.borderColor = UIColor.gray.cgColor
self.customAlert.clipsToBounds = false
let radius: CGFloat = self.customAlert.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: self.customAlert.frame.height))
self.customAlert.layer.masksToBounds = false
self.customAlert.layer.cornerRadius = 8; // if you like rounded corners
self.customAlert.layer.shadowOffset = CGSize(width:-15, height:20);
self.customAlert.layer.shadowRadius = 5;
self.customAlert.layer.shadowOpacity = 0.5;
self.customAlert.layer.shadowPath = shadowPath.cgPath
self.customAlert.byMonthlyBtn.addTarget(self, action: #selector(button1tapped), for: .touchUpInside)
self.customAlert.byAnnuallyBtn.addTarget(self, action: #selector(button2tapped), for: .touchUpInside)
}
And its looks like below screenshot
Any suggestions?
private func commonInit() {
Bundle.main.loadNibNamed("CustomAlertView", owner: self)
guard let content = customAlertView else { return }
content.frame = self.bounds
content.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.addSubview(content)
}
Your problem is you are using the CustomAlertView you loaded. Try adjust your code like below.
private func commonInit() {
guard let view = Bundle.main.loadNibNamed("CustomAlertView", owner: self)?.first as? CustomAlertView else {
return
}
view.frame = bounds
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
addSubview(view)
}
I followed this code to create a taller UINavigationBar:
var heightIncrease: CGFloat = 38.0
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.transform = CGAffineTransformMakeTranslation(0, -heightIncrease)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
override func sizeThatFits(size: CGSize) -> CGSize {
var newSize = super.sizeThatFits(size)
newSize.height += heightIncrease
return newSize
}
override func layoutSubviews() {
super.layoutSubviews()
for view in self.subviews {
if (NSStringFromClass(view.classForCoder).containsString("UINavigationBarBackground")) {
view.frame.origin.y = self.bounds.origin.y + heightIncrease - statusBarHeight
view.frame.size.height = self.bounds.size.height + statusBarHeight
}
}
}
var statusBarHeight: CGFloat {
return UIApplication.sharedApplication().statusBarFrame.size.height
}
Now I want to add a view from an XIB to that bottom part. My first thought was to do something like this:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.transform = CGAffineTransformMakeTranslation(0, -heightIncrease)
if let accessoryView = NSBundle.mainBundle()
.loadNibNamed("NavBarAccessoryView", owner: self, options: nil)
.first as? NavBarAccessoryView {
accessoryView.frame.size.width = self.bounds.size.width
accessoryView.frame.origin.y = 75
self.addSubview(accessoryView)
}
}
It looks ok, but I can't select a segment in the segmented control, it's as if it were just a picture:
Is there a better way to do this? I'm sorry if it's a silly question or if my attempt makes no sense, I'm new at this and so far I've only dealt with views and stuff from the interface builder.
i write extension :
extension UIView {
static func instanceFromNibByClassName() -> UIView {
let nibName = stringFromClass(self as AnyClass)
return NSBundle.mainBundle().loadNibNamed(nibName, owner: nil, options: nil).first! as! UIView
}
}
so i can get instance like this:
var coverTableViewCell=YQEventCoverTableViewCell.instanceFromNibByClassName() as! YQEventCoverTableViewCell
I'm trying to initialise an MPMoviePlayerController in a custom UIView. I do hear the sound but no view. I think something is wrong with initialising the view. I tried it by implementing in the ViewController, then it does work.
Here my code:
import UIKit
import MediaPlayer
class CustomView: UIView {
var sponsor: Sponsors!
var videoContainer = UIView()
var videoPlayer = MPMoviePlayerController()
override init(frame: CGRect) {
super.init(frame: frame)
//Init
layer.cornerRadius = 3.0
backgroundColor = UIColor.whiteColor()
//VideoContainer
videoContainer.backgroundColor = UIColor.blackColor()
//Adding the views
addSubview(videoContainer)
videoContainer.addSubview(videoPlayer.view)
}
//MARK: InitCoder
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
//MARK: AddDataToView
func addDataToView(sponsor: Sponsors) {
//VideoPlayerx
let path = NSBundle.mainBundle().pathForResource("movie5", ofType:"mov")
let url = NSURL.fileURLWithPath(path!)
videoPlayer = MPMoviePlayerController(contentURL: url)
videoPlayer.prepareToPlay()
}
//MARK: LayoutSubViews
override func layoutSubviews() {
super.layoutSubviews()
//VideoContainer
videoContainer.frame = CGRectMake(8, 8, frame.size.width - 16, 219)
//Video
videoPlayer.view.frame = CGRectMake(8, 8, frame.size.width - 16, 219)
videoPlayer.scalingMode = .AspectFill
You need to set frame and add subview after create videoPlayer object. In addDataToView you init videoPlayer again so every settings before that are cleared.
Does anyone know how add a gradient to the bottom of a uitableviewcell or the uiimageview like the image shown below does?
Add this class into your project (swift):
class UIGradientImageView: UIImageView {
let myGradientLayer: CAGradientLayer
override init?(frame: CGRect){
myGradientLayer = CAGradientLayer()
super.init(frame: frame)
self.setup()
addGradientLayer()
}
func addGradientLayer(){
if myGradientLayer.superlayer == nil{
self.layer.addSublayer(myGradientLayer)
}
}
required init(coder aDecoder: NSCoder){
myGradientLayer = CAGradientLayer()
super.init(coder: aDecoder)
self.setup()
addGradientLayer()
}
func getColors() -> [CGColorRef] {
return [UIColor.clearColor().CGColor, UIColor(red: 0, green: 0, blue: 0, alpha: 0.5).CGColor]
}
func getLocations() -> [CGFloat]{
return [0.5, 0.9]
}
func setup() {
myGradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
myGradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
let colors = getColors()
myGradientLayer.colors = colors
myGradientLayer.opaque = false
myGradientLayer.locations = getLocations()
}
override func layoutSubviews() {
super.layoutSubviews()
myGradientLayer.frame = self.layer.bounds
}
}
UPDATE: Objective-C translated solution. Credits to #SleepsOnNewspapers.
#import "UIGradientImageView.h"
#interface UIGradientImageView()
#property (nonatomic, strong) CAGradientLayer *myGradientLayer;
#end
#implementation UIGradientImageView
-(instancetype)initWithFrame:(CGRect)frame{
if(self){
self = [super initWithFrame:frame];
self.myGradientLayer = [[CAGradientLayer alloc]init];
[self setup];
[self addGradientLayer];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if(self){
self = [super initWithCoder:aDecoder];
self.myGradientLayer = [[CAGradientLayer alloc]init];
[self setup];
[self addGradientLayer];
}
return self;
}
-(void)addGradientLayer{
if (self.myGradientLayer.superlayer == nil) {
[self.layer addSublayer:self.myGradientLayer];
}
}
Make your UIImageView class on your storyboard to be this one instead of default.