FBNativeAdView is not presented - Swift - ios

I am trying to present Facebook Native Ad Template with no luck.
class ViewController: UIViewController, FBNativeAdDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
facebookAdViewContainer.backgroundColor = UIColor.greenColor()
let nativeAd = FBNativeAd(placementID: <id>)
nativeAd.delegate = self
nativeAd.loadAd()
...
}
func nativeAdDidLoad(nativeAd: FBNativeAd)
{
let attributes = FBNativeAdViewAttributes()
attributes.backgroundColor = UIColor.blueColor()
let adview = FBNativeAdView(nativeAd: nativeAd, withType:FBNativeAdViewType.GenericHeight300)//, withAttributes: attributes)
adview.hidden = false
self.topBannerViewContainer.addSubview(adview)
}
...
}
As you can see in the picture, the ad is not showing. At least I would expect to see blue background of the ad, but all I can see is the green background of the container

Related

How to change prompt color in Swift 5 iOS16

I am trying to change the color of the prompt in my navigation controller so that it is white not black for iOS16.
The following code changes the title but not the prompt. My code is:
import UIKit
class ParentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor.blue //UIColor.lincsNavBarBlueColor()
appearance.titleTextAttributes[NSAttributedString.Key.foregroundColor] = UIColor.white
navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
navigationItem.title = "Hello there"
navigationItem.prompt = "This is the prompt"
}
}
What do I need to add to change the prompt color? Thanks.
This seems like a bug and I doubt Apple will fix it.
I've worked around it by subclassing the UINavigationController and diving for the label.
#objc
final class NavigationControllerWithPrompt: UINavigationController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
changePromptColor()
}
private func changePromptColor() {
let promptView = navigationBar.subviews.first { view in
return String(describing: type(of: view)) == "_UINavigationBarModernPromptView"
}
let promptLabel = promptView?.subviews.compactMap{ $0 as? UILabel }.first
promptLabel?.textColor = UIColor.white
}
}

Admob Native Advanced Not Clickable

I have created a custom View Class that inherits from GADNativeContentAdView Class. When I receive an advertisement and the delegate is called, I fill my custom view with the data as shown below.
Everything looks fine but the problem is that it is not clickable at all. I tried to set the actionbutton userinteraction to false, but still won't work.
I also tried to register using following:
-(void)registerAdView:(UIView *)adView
clickableAssetViews:(NSDictionary *)clickableAssetViews
nonclickableAssetViews:
(NSDictionary *)nonclickableAssetViews;
Any idea how to get it to work?
- (void)setNativeContent:(GADNativeContentAd *)nativeContent
{
self.nativeContentAd = nativeContent;
headlineLabel.text = nativeContent.headline;
bodyLabel.text = nativeContent.body;
advertiserImage.image = ((GADNativeAdImage *)nativeContent.images.firstObject).image;
[actionButton setTitle:nativeContent.callToAction forState:UIControlStateNormal];
if (nativeContent.logo && nativeContent.logo.image)
{
advertiserLogo.image = nativeContent.logo.image;
}
else
{
advertiserLogo.image = advertiserImage.image;
}
NSDictionary *clickableArea = #{GADNativeContentHeadlineAsset:headlineLabel, GADNativeContentImageAsset:advertiserImage, GADNativeContentCallToActionAsset:actionButton};
NSDictionary *nonClickableArea = #{GADNativeContentBodyAsset:bodyLabel};
[nativeContent registerAdView:self clickableAssetViews:clickableArea nonclickableAssetViews:nonClickableArea];
}
I finally figured out a way to make the entire native ad clickable without using a .xib. I subclassed GADNativeContentAdView and created a tappableOverlay view that I assigned to an unused asset view in its superclass. In this case, it was the callToActionView. Then I used the not-so-documented GADNativeContentAd.registerAdView() method:
- (void)registerAdView:(UIView *)adView
clickableAssetViews:(NSDictionary<GADNativeContentAdAssetID, UIView *> *)clickableAssetViews
nonclickableAssetViews: (NSDictionary<GADNativeContentAdAssetID, UIView *> *)nonclickableAssetViews;
Here's a Swift 4 example:
class NativeContentAdView: GADNativeContentAdView {
var nativeAdAssets: NativeAdAssets?
private let myImageView: UIImageView = {
let myImageView = UIImageView()
myImageView.translatesAutoresizingMaskIntoConstraints = false
myImageView.contentMode = .scaleAspectFill
myImageView.clipsToBounds = true
return myImageView
}()
private let myHeadlineView: UILabel = {
let myHeadlineView = UILabel()
myHeadlineView.translatesAutoresizingMaskIntoConstraints = false
myHeadlineView.numberOfLines = 0
myHeadlineView.textColor = .black
return myHeadlineView
}()
private let tappableOverlay: UIView = {
let tappableOverlay = UIView()
tappableOverlay.translatesAutoresizingMaskIntoConstraints = false
tappableOverlay.isUserInteractionEnabled = true
return tappableOverlay
}()
private let adAttribution: UILabel = {
let adAttribution = UILabel()
adAttribution.translatesAutoresizingMaskIntoConstraints = false
adAttribution.text = "Ad"
adAttribution.textColor = .white
adAttribution.textAlignment = .center
adAttribution.backgroundColor = UIColor(red: 1, green: 0.8, blue: 0.4, alpha: 1)
adAttribution.font = UIFont.systemFont(ofSize: 11, weight: UIFont.Weight.semibold)
return adAttribution
}()
override var nativeContentAd: GADNativeContentAd? {
didSet {
if let nativeContentAd = nativeContentAd, let callToActionView = callToActionView {
nativeContentAd.register(self,
clickableAssetViews: [GADNativeContentAdAssetID.callToActionAsset: callToActionView],
nonclickableAssetViews: [:])
}
}
}
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .white
isUserInteractionEnabled = true
callToActionView = tappableOverlay
headlineView = myHeadlineView
imageView = myImageView
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
addSubview(myHeadlineView)
addSubview(myImageView)
addSubview(adAttribution)
addSubview(tappableOverlay)
}
// override func updateConstraints() {
// ....
// }
}
Just be sure to pin the tappableOverlay to its superview edges so that they're the same size...in updateConstraints().
Inside the method simply you can create and place Ad in view hierarchy.
GADNativeContentAdView *contentAdView = [[NSBundle mainBundle] loadNibNamed:#"NativeAdView" owner:nil options:nil].firstObject;
After assigning the properties, associate the content Ad view with the content ad object. This is required to make the ad clickable.
contentAdView.nativeContentAd = nativeContentAd;
Only AdMob whitelisted publishers can use the registerAdView API :)
All publishers can use xib to create an ad view.
Don't forget to link custom GADUnifiedNativeAdView outlets to your UILabels, UIButtons and ImageViews, so GADUnifiedNativeAdView will know what to interact with
In my case it was cause I created my views without xib.
In this case just set mediaView property to your GADNativeAdView
here the minimum working code
final class EndBannerController: UIViewController {
private let adId: String
private let adView = GADNativeAdView()
private let mediaView = GADMediaView()
private var adLoader: GADAdLoader?
init(adId: String) {
self.adId = adId
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { return nil }
override func viewDidLoad() {
super.viewDidLoad()
adView.frame = view.bounds
view.addSubview(adView)
mediaView.frame = view.bounds
adView.mediaView = mediaView
adView.addSubview(mediaView)
let loader = GADAdLoader(
adUnitID: adId,
rootViewController: self,
adTypes: [.native],
options: nil
)
loader.delegate = self
self.adLoader = loader
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.loadBannerAd()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
adView.frame = view.bounds
mediaView.frame = view.bounds
}
private func loadBannerAd() {
let request = GADRequest()
request.scene = view.window?.windowScene
self.adLoader?.load(request)
}
}

Swift 3 - Changing background colour of all view controllers, via switch(Dark mode/Night mode)

i crated a switch that lets the user change the background colour (dark mode). This only works on the view controller that the code is linked with. How would i set it so when the switch is activated to either dark or light mode, every view controller in my application would change, not just the one. Heres my code:
import UIKit
class DarkMode: UIViewController {
#IBOutlet var DarkSwitch: UISwitch!
#IBOutlet var LightSwitch: UISwitch!
var DarkisOn = Bool()
var LightisOn = Bool()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let DarkDefault = UserDefaults.standard
DarkisOn = DarkDefault.bool(forKey: "DarkDefault")
let LightDefault = UserDefaults.standard
LightisOn = LightDefault.bool(forKey: "LightDefault")
if (DarkisOn == true) {
DarkSwitch.isOn = true
LightSwitch.isOn = false
//run dark theme
DarkTheme()
}
if (LightisOn == true) {
DarkSwitch.isOn = false
LightSwitch.isOn = true
//run light theme
LightTheme()
}
}
func DarkTheme() //dark colour
{
self.view.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 1.0)
}
func LightTheme() //light colour
{
self.view.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}
#IBAction func DarkAction(_ sender: Any)
{
DarkSwitch.isOn = true
LightSwitch.isOn = false
//run dark theme func
DarkTheme()
let DarkDefault = UserDefaults.standard
DarkDefault.set(true, forKey: "DarkDefault")
let LightDefault = UserDefaults.standard
LightDefault.set(false, forKey: "LightDefault")
}
#IBAction func LightAction(_ sender: Any)
{
DarkSwitch.isOn = false
LightSwitch.isOn = true
//run light theme func
LightTheme()
let DarkDefault = UserDefaults.standard
DarkDefault.set(false, forKey: "DarkDefault")
let LightDefault = UserDefaults.standard
LightDefault.set(true, forKey: "LightDefault")
}
}
You can create a base class like this (This is something I have used.)
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = MainColor
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]//user global variable
self.navigationController?.navigationBar.barStyle = UIBarStyle.black //user global variable
self.navigationController?.navigationBar.tintColor = UIColor.white //user global variable
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Setup all your theme here.
All the color value should be global which you can change from another ViewController.
And now declare your all ViewControllers like this
class HomeViewController: BaseViewController {
}
This way HomeViewController will have all the appearance you set in BaseViewController.
Now All you have to do is change those global variables for color value.
For one of my projects I created a class that controlled the UI colour scheme across all my ViewControllers.
class UIColourScheme {
func set(for viewController: UIViewController) {
viewController.view.backgroundColor = bgColour
...
}
var bgColour = UIColor.black
static let instance = UIColourScheme()
}
I would then call this function in viewDidLoad() for every ViewController
class MyViewController : UIViewController {
func viewDidLoad() {
...
UIColourScheme.instance.set(for:self)
}
}
My colour scheme class setup colours for everything but it could be simplified to just the background colour as above.
you can use this
protocol colorable {
func setcolor(color: UIColor)
}
class HomeVC: colorable {
}
I modified viewWillAppear method. And added dark mode based on the time of the day.
You do not need to format the time/hours you receive back you may wanna use it as is in conditional statement.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
// get time of the day
let hour = Calendar.current.component(.hour, from: Date())
print(hour)
if hour >= 14 {
overrideUserInterfaceStyle = .dark
}
else {
overrideUserInterfaceStyle = .light
}
}

Making a UIView update behind another one in the same view controller

I'm working in swift to make an app the uses the cocoapod framework BBSlideoutMenu to display a menu. I am also using the cocoapod framework ChameleonFramework. What I'm trying to do is make the hamburger button that I'm using change colour when it is opened. I haven't yet implemented it, but I also want to make the bar on top transparent. I've recorded it here so you can see what is happening. Basically, the view only gets updated when I slide away the menu.
Disclaimer: I am aware that using a hamburger menu is viewed as bad code design, unfortunately it is what I need in this app.
Here is my code:
import UIKit
import BBSlideoutMenu
import ChameleonFramework
class ViewController: UIViewController, BBSlideoutMenuDelegate {
#IBOutlet var slideMenu: BBSlideoutMenu!
var button: HamburgerButton! = nil
var menuOpen = false;
let screenSize: CGRect = UIScreen.mainScreen().bounds
let topBar = UIView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height * 0.1))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
view.backgroundColor = UIColor.whiteColor()
topBar.backgroundColor = FlatRed()
button = HamburgerButton(frame: CGRectMake(0, 20, 54, 54))
button.addTarget(self, action: #selector(toggleMenu(_:)), forControlEvents:.TouchUpInside)
topBar.addSubview(button)
view.addSubview(topBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
slideMenu.setupEdgePan()
slideMenu.slideDirection = .Right
slideMenu.shrinkAmount = 0
slideMenu.slideTravelPercent = 0.87
slideMenu.menuOffset = 0
slideMenu.zoomFactor = 1
slideMenu.springEnabled = false
slideMenu.backgroundColor = FlatRed()
slideMenu.delegate = self
slideMenu.setupEdgePan()
}
func toggleMenu(sender : HamburgerButton!) {
if(menuOpen) {
slideMenu.dismissSlideMenu(animated: true, time: nil)
} else {
slideMenu.presentSlideMenu(true) { () -> Void in
//Runs after menu is presented
}
}
}
func didPresentBBSlideoutMenu(menu: BBSlideoutMenu) {
menuOpen = true
button.changeColor(UIColor.blackColor())
}
func didDismissBBSlideoutMenu(menu: BBSlideoutMenu) {
menuOpen = false
button.changeColor(UIColor.whiteColor())
}
}
I am using this hamburger menu button, which has been created with CoreGraphics and QuartzCore, and have added the following function for change colour.
func changeColor(color: UIColor) {
for layer in [ self.topStroke, self.middleStroke, self.bottomStroke ] {
layer.fillColor = nil
layer.strokeColor = color.CGColor
layer.lineWidth = 4
layer.miterLimit = 4
layer.lineCap = kCALineCapRound
layer.masksToBounds = true
let strokingPath = CGPathCreateCopyByStrokingPath(layer.path, nil, 4, .Round, .Miter, 4)
layer.bounds = CGPathGetPathBoundingBox(strokingPath)
layer.actions = [
"strokeStart": NSNull(),
"strokeEnd": NSNull(),
"transform": NSNull()
]
self.layer.addSublayer(layer)
}
}
Edit: I have tried using setNeedsDisplay on the button, the topBar, and both of them consecutively in the functions toggleMenu, didPresentBBSlideoutMenu and didDismissBBSlideoutMenu and it didn't work
I have also tried calling it on the actual view (self.view)
Try calling setNeedsDisplay the button.

Using Page View Controller inside Tab Swift

MY WORK SO FAR:
So I have a Tab bar that looks like this:
When I click on "Canteen" I want to be directed to a Page View Controller where I can swipe between different pages but stay on the same tab.
I have this somewhat working:
I have the Storyboard setup like this:
As you can see that segue above is coming from the Tab Bar Controller.
The third view (Can Page Item Controller, ID: "CanItemController) is used for all pages in the page view.
The second view above (Page View Controller, ID: "CanPageController) is used for controlling the Pages (duh)
The first view (CanteenViewController) contains all the code and makes all the connections. This is where everything goes on. The code inside this class is here:
import UIKit
class CanteenViewController: UIViewController, UIPageViewControllerDataSource {
// MARK: - Variables
private var pageViewController: UIPageViewController?
private let contentImages = ["Radar-512.png",
"dartp.png",
"roomp.png",
"abnews.png",
"canteenp.png"];
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControl()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("CanPageController") as! UIPageViewController
pageController.dataSource = self
if contentImages.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
// MARK: - UIPageViewControllerDataSource
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! CanPageItemController
if itemController.itemIndex > 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! CanPageItemController
if itemController.itemIndex+1 < contentImages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
private func getItemController(itemIndex: Int) -> CanPageItemController? {
if itemIndex < contentImages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("CanItemController") as! CanPageItemController
pageItemController.itemIndex = itemIndex
pageItemController.imageName = contentImages[itemIndex]
return pageItemController
}
return nil
}
// MARK: - Page Indicator
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return contentImages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
I HAVE 2 PROBLEMS:
I can't see any page indicators at all.
This comes from the following code:
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
Is there a way I can add a page indicator in the storyboard and reference that programatically. That way maybe I could add constraints and have more control. I think the page indicator might be hidden behind the Tab Bar. Though constraints are also giving me issues, which leads me to problem 2
As you can see in the Item Controller, I have a UIImageView and the constraints are all set right. But when I run the app the image appears for a second (completely out of proportion) and then disappears. i.e - my constraints simply don't work properly
Question
Is my approach in general just wrong? Or is there a few little changes I can make to fix the above problems. I I've been following a tutorial (on Ray Wenderlich I think), and it all worked fine until I tried to integrate it with my Tab Bar.
Leave all above thing, just do as following.
Edited : As per Swift 5
class CanteenViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet var scrHelp: UIScrollView!
#IBOutlet var pageControl: UIPageControl!
var page = 0
let arrContent: [[String: Any]] = [["name" : "Title1", "icon" : "Radar-512"],
["name" : "Title2", "icon" : "dartp"],
["name" : "Title3", "icon" : "roomp"],
["name" : "Title4", "icon" : "abnews"],
["name" : "Title5", "icon" : "canteenp"]]
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Canteen"
// Do any additional setup after loading the view, typically from a nib.
self.createHelpView()
self.pageControl.backgroundColor = UIColor.clear
self.pageControl.pageIndicatorTintColor = UIColor.lightGray
self.pageControl.currentPageIndicatorTintColor = UIColor(red: 251/255, green: 108/255, blue: 108/255, alpha: 1.0)
self.pageControl.tintAdjustmentMode = UIView.TintAdjustmentMode.dimmed
self.pageControl.numberOfPages = self.arrContent.count
self.pageControl.currentPage = 0
}
func createHelpView() {
var x = 50
var i = 0
for item in self.arrContent {
let lblTitle = UILabel(frame: CGRect(origin: CGPoint(x: CGFloat(x), y: 10), size: CGSize(width: CGFloat(self.scrHelp.frame.width-100), height: 25)))
lblTitle.autoresizingMask = UIView.AutoresizingMask.flexibleBottomMargin
lblTitle.backgroundColor = UIColor.clear
lblTitle.font = UIFont.systemFont(ofSize: 17)
lblTitle.textAlignment = NSTextAlignment.center
lblTitle.textColor = UIColor.black
lblTitle.text = item["name"] as? String //self.arrTitle[i]
self.scrHelp.addSubview(lblTitle)
let imgView = UIImageView(frame: CGRect(origin: CGPoint(x: CGFloat(x), y: 50), size: CGSize(width: CGFloat(self.scrHelp.frame.width-100), height: CGFloat(self.scrHelp.frame.height-150))))
imgView.autoresizingMask = UIView.AutoresizingMask.flexibleBottomMargin
imgView.backgroundColor = UIColor.clear
imgView.image = UIImage(named: (item["icon"] as! String))
imgView.contentMode = UIView.ContentMode.scaleAspectFit
self.scrHelp.addSubview(imgView)
x = x + Int(self.scrHelp.frame.width)
i = i + 1
}
self.scrHelp.contentSize = CGSize(width: (CGFloat(self.arrContent.count) * self.view.frame.width), height: 0)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = CGFloat(self.scrHelp.frame.width)
let fractionalPage = self.scrHelp.contentOffset.x / pageWidth
self.page = lround(CDouble(fractionalPage))
self.pageControl.currentPage = self.page
}
}
At last, add UIScrollView and UIPageControl to you storyboard and set respective outlet and constraint.

Resources