I wanted to use BCMeshTransformView library into my swift project. I've created an empty swift project and added the library via cocoa pods.
Here's my ViewController class:
import UIKit
import BCMeshTransformView
class ViewController: UIViewController {
var transformView:BCMeshTransformView!
var imageView:UIImageView!
var transform:BCMutableMeshTransform!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
transformView = BCMeshTransformView(frame: self.view.bounds)
transformView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
imageView = UIImageView(image: UIImage(named: "picture.jpg")!)
imageView.center = CGPoint(x: transformView.contentView.bounds.midX, y: transformView.contentView.bounds.midY)
transformView.contentView.addSubview(imageView)
transformView.diffuseLightFactor = 0.0
transform = BCMutableMeshTransform.identityMeshTransform(withNumberOfRows: 20, numberOfColumns: 20)
transform.mapVertices { (vertex, vertexIndex) -> BCMeshVertex in
return BCMeshVertex(from: vertex.from, to: vertex.to)
}
transformView.meshTransform = transform
self.view.addSubview(transformView)
}
}
When I'm running the app nothing is showing. It's entirely white.
Removing this code:
transform = BCMutableMeshTransform.identityMeshTransform(withNumberOfRows: 20, numberOfColumns: 20)
transform.mapVertices { (vertex, vertexIndex) -> BCMeshVertex in
return BCMeshVertex(from: vertex.from, to: vertex.to)
}
transformView.meshTransform = transform
doesn't change anything.
But when in xcode I'm switching to "Show UI hierarchy" I can see an image:
Here's a whole sample project:
http://www116.zippyshare.com/v/IUTXbKJg/file.html
Why I cannot see anything? I tried making an example as simple as possible.
Looks like that was a problem with that library codun't find shader files. I had to copy BCMeshShader.fsh and BCMeshShader.vsh to my project.
Related
Is it possible to put a loading animation over the VNDocumentViewController? As in, when the user presses the Save button, is there a way for me to somehow indicate that the Vision is processing the image and hasn't frozen? Right now, in my app, there is a long pause between the user pressing Save and the actual image being processed.Here is an example from another post of what I'm trying to create
Here is one example of adding a loading indicator using UIActivityIndicatorView().
startAnimating() to start the animation and stopAnimation() to stop the animation.
iOS - Display a progress indicator at the center of the screen rather than the view
guard let topWindow = UIApplication.shared.windows.last else {return}
let overlayView = UIView(frame: topWindow.bounds)
overlayView.backgroundColor = UIColor.clear
topWindow.addSubview(overlayView)
let hudView = UIActivityIndicatorView()
hudView.bounds = CGRect(x: 0, y: 0, width: 20, height: 20)
overlayView.addSubview(hudView)
hudView.center = overlayView.center
hudView.startAnimating()
Alternatively, you could look into using Cocoapod MBProgressHud
https://cocoapods.org/pods/MBProgressHUD
There's a way you can extend a class in Swift that captures this problem well. The idea is you want a UIActivityIndicator in your VNDocumentCameraViewController. But we'd like that to be a part of every version of this we use. We could simply embed the DocumentVC's view into our current view and superimpose a UIActivityIndicator above it in the view stack, but that's pretty hacky. Here's a quick way we can extend any class and solve this problem
import VisionKit
import UIKit
extension VNDocumentCameraViewController {
private struct LoadingContainer {
static var loadingIndicator = UIActivityIndicatorView()
}
var loadingIndicator: UIActivityIndicatorView {
return LoadingContainer.loadingIndicator
}
func animateLoadingIndicator() {
if loadingIndicator.superview == nil {
view.addSubview(loadingIndicator)
//Setup your constraints through your favorite method
//This constrains it to the very center of the controller
loadingIndicator.frame = CGRect(
x: view.frame.width / 2.0,
y: view.frame.height / 2.0,
width: 20,
height: 20)
//Setup additional state like color/etc here
loadingIndicator.color = .white
}
loadingIndicator.startAnimating()
}
func stopAnimatingLoadingIndicator() {
loadingIndicator.stopAnimating()
}
}
The place we can call these functions are in the delegate methods for VNDocumentCameraViewController that you implement in your presenting ViewController:
func documentCameraViewController(
_ controller: VNDocumentCameraViewController,
didFinishWith scan: VNDocumentCameraScan
) {
controller.animateLoadingIndicator()
}
I've created an #IBOutlet weak var animationView: AnimationView! Then on ViewController I added a UIView changed its class from UIView to AnimationView. The after connecting the outlet I'm adding this code in viewDidLoad() of my class:
let animation = Animation.named("sticky", subdirectory: "Lottie-files")
animationView.animation = animation
animationView.loopMode = .loop
animationView.contentMode = .scaleAspectFill
Then in viewDidAppear() I've added:
animationView.play()
But when I run it nothing shows up. I also see this in the terminal:
[Storyboard] Unknown class AnimationView in Interface Builder file.
This warning is solved by doing
But still the animation is not appearing. No warning, no error it just not displaying.
You should start animation in viewDidAppear or something called after viewDidLoad, for example: viewWillAppear
public override func viewDidLoad() {
super.viewDidLoad()
addAnimation(to: animationView, name: "sticky")
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
animationView.play()
}
private func addAnimation(to view: AnimationView, name: String) {
let animation = Animation.named(name, subdirectory: "Lottie-files")
view.animation = animation
view.loopMode = .loop
view.contentMode = .scaleAspectFill
}
BONUS
Ekramul Hoque's Article about View Controller's Lifecycle
Make sure these
You should write Lottie to your view's Identity Inspector section in Interface Builder's right bar.
Check for subdirectory path. It can be because Xcode is unable to locate file in Lottie-files subdirectory. Try moving it in the main directory and try.
You can set programmatically
import Lottie
then add animation view in your view controller, set lottie animation in your storyboard -> animationView -> class -> AnimationView and module -> Lottie
#IBOutlet weak var animationView: AnimationView!
//Initialise a Lottie view with frame
let customAnimationView = AnimationView(name: "Your lotti file name")
customAnimationView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
//Do your configurations
customAnimationView.loopMode = .loop
customAnimationView.backgroundBehavior = .pauseAndRestore
//And play
customAnimationView.play()
animationView.addSubview(customAnimationView)
As per the lottie document you should call
play()
function inside viewDidAppear.
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
animationView.play()
}
Please check the following link
https://github.com/airbnb/lottie-ios/blob/master/Example/lottie-swift/ViewController.swift
NOTE : In some case you need to check sub directory problem
You need to add Folder References
Not a Groups
for more information on this section please check the following link.
http://www.thomashanning.com/xcode-groups-folder-references/
there is a requirement like add an imageview to all viewcontrollers but I have 150+ xib's and it is time consuming to put imageview in every single xib.
Is there a common way to do it? I googled but nothing useful found.
Any help would be appreciated.
It will be easy if you use base class like this
class BaseVC: UIViewController
{
var imageView:UIImageView = UIImageView.init()
override func viewDidLoad() {
super.viewDidLoad()
addImageView()
}
override func viewWillAppear(_ animated: Bool) {
//self.view.bringSubview(toFront: imageView) //To bring imageview infront of other views put this method as per your requirement
}
func addImageView(name:String = "default")
{
let image = UIImage(named: name)
imageView.image = image
imageView.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
//view.addSubview(imageView)
view.insertSubview(imageView, at: 0) /*For put image view below all image*/
}
}
You need to derive all your view controller from this like this
class YourVC: BaseVC
also you can change the image with different viewcontrollers.
like
class YourVC: BaseVC
{
override func viewDidLoad() {
super.viewDidLoad()
addImageView(name:"xyz")
}
}
you can write an extension for UIView to add imageview into it and run it into every your viewcontrollers.
extension UIView {
func addImage() {
let imageView = UIImageView(frame: frame)
imageView.image = UIImage(named: "Your Image Name")
addSubview(imageView)
imageView.didMoveToSuperview()
}
}
Create New ViewController without storyboard.
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setImageView()
}
func setImageView() {
let thisImageView = UIImageView(frame: CGRect(x: 10, y: 10, width: 70, height: 70))
thisImageView.image = UIImage(named: "your image name")
view.addSubview(thisImageView)
}
}
now you can set this BaseViewController as delegate of your project's ViewControllers.
import UIKit
class MainViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
now you have this ImageView in MainViewController and all ViewControllers have BaseViewContoller as delegate.
Hope to be useful. Also sorry about my English.
TL;DR No. Based on my understanding of what you are imagining, no you can't write a function to add a UIImageView to every one of your viewControllers.
Long answer:
You need to create a separate controller swift file for each View and set it up in that file. You could create a supporting file in which you setup up the the ImageView then call in in the viewDidLoad for each view controller. (You could even make this an extension of UIView so you can just call something like self.setUpImageView())
My personal recommendation would be to drop the xibs as soon as you can and recreate everything pragmatically, I know it's a headache to throw all your work away but it is really worth it in the end on top of just being good practice. I have a file that I found that makes autolayout a breeze that I can share with you if you'd like. I used to really enjoy storyboards and xibs myself but they are a hassle that just isn't worth it anymore and cause such a headache in situation like this.
I have a strange problem. I am trying to use Kingfisher in order to load and an cache an Image from Firebase in my app. The problem is that kKingfisher does not download the image. I am using a Placeholder Image that is locally stored and the scroll view displays that Image. If I remove the placeholder part from the command, the app crashes. So I know the Kingfisher function works by at least placing the placeholder Image into the UIImageView but not the image from the URL. Here is the code:
Can you point me to the right direction?
import UIKit
import Kingfisher
class Backprogramme: UIViewController {
override var prefersStatusBarHidden: Bool {
return true
}
#IBOutlet var BackPScroll: UIScrollView!
var imageArray = [UIImage]()
var folie1Image = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
let folie1URL = URL(string: "https://firebasestorage.googleapis.com/v0/b/backmaster-cdb60.appspot.com/o/Folie1.PNG?alt=media&token=efcb8e93-b817-41f3-a96f-946fd47cf468")!
folie1Image.kf.setImage(with: folie1URL, placeholder: #imageLiteral(resourceName: "first"))
imageArray = [folie1Image.image!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.BackPScroll.frame.width, height: self.BackPScroll.frame.height)
BackPScroll.contentSize.width = BackPScroll.frame.width * CGFloat(i+1)
BackPScroll.addSubview(imageView)
}
// Do any additional setup after loading the view.
}
}
I had the same issue , discovered I had this in the log "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection" .
I fixed it by adding NSAppTransportSecurity as a Dictionary in the info.plist and then I added Allow Arbitrary Loads boolean with YES as a value . It worked instantly.
I integrated MoPub advertising for my iOS app to run some native ads in my UITableViewController (actually, it's a PFQueryTableViewController because I'm using Parse to load data into the tableView).
Everything is running fine - the console shows that ads are being loaded successfully, and I can see the extra cell in my tableView where the ad should be - the problem is that none of the content for the ad is showing up; I only see a blank cell.
The problem doesn't seem to be from MoPub. I think I'm setting up my cell incorrectly because I can't get ANYTHING to show up there.
I have tried 2 things.
Setting up the cell using storyboard. I added a new cell to my UITableViewController and created a new class for it, NativeAdCell. I designed IBOutlets and connected them to the class file.
The content is loaded through a MoPub function like so:
func layoutAdAssets(adObject: MPNativeAd!) {
adObject.loadIconIntoImageView(iconImageView)
adObject.loadTitleIntoLabel(titleLabel)
adObject.loadCallToActionTextIntoButton(callToActionButton)
adObject.loadImageIntoImageView(mainImageView)
adObject.loadTextIntoLabel(mainTextLabel)
}
The app crashes at the first line with console output (lldb).
Adding the outlets programmatically. In the NativeAdCell file I add outlets like so:
var mainTextLabel = UILabel()
var titleLabel = UILabel()
var iconImageView = UIImageView()
var mainImageView = UIImageView()
var callToActionButton = UIButton()
And later setting their frames.
The content is loaded with the same MoPub function. Now there is no crash, but the ad cell shows up completely blank with no content. Even if I manually set mainTextLabel.text = "Please show up" nothing will show up.
The crash when I try to load the IBOutlets makes me think something is wrong with the way I'm linking up the NativeAdCell to the tableView, but it seems like the MoPub SDK should handle this.
Can anybody spot the problem based on this info?
I achieved this without IBOutlets as follows, it's not well documented so I figured this might help someone out who is looking to use the MoPub SDK with custom cells for native ads
//
// AdTableViewCell.swift
// Trending-News
//
// Created by Conor Griffin on 22/07/2015.
// Copyright (c) 2015 Conor Griffin. All rights reserved.
//
import UIKit
import MoPub
class AdTableViewCell: UITableViewCell, MPNativeAdRendering {
var iconImageView: UIImageView! = UIImageView()
var titleLabel: UILabel! = UILabel()
var mainTextLabel: UILabel! = UILabel()
var advertIndicator: CGSponsoredLinkLabel! = CGSponsoredLinkLabel()
var adCorner: CGCornerHighlight! = CGCornerHighlight()
static func sizeWithMaximumWidth(maximumWidth: CGFloat) -> CGSize {
return CGSize(width: maximumWidth, height: 100)
}
override func layoutSubviews() {
super.layoutSubviews()
let width = CGRectGetWidth(frame)
let cellFrame = CGRect(x: 0, y: 0, width: width, height: 100)
iconImageView.layer.borderColor = UIColor.grayColor().CGColor
iconImageView.layer.borderWidth = 1
iconImageView.frame = CGRectMake(10, 10, 80, 80)
contentView.addSubview(iconImageView)
titleLabel.frame = CGRectMake(100, 10, self.frame.width - 110, 25)
contentView.addSubview(titleLabel)
mainTextLabel.frame = CGRectMake(100, 35, self.frame.width - 110, self.frame.height - 65)
contentView.addSubview(mainTextLabel)
mainTextLabel.numberOfLines = 3
mainTextLabel.font = UIFont.systemFontOfSize(11.0)
advertIndicator.frame = CGRectMake(100, self.frame.height - 30, self.frame.width - 110, self.frame.height - 80)
contentView.addSubview(advertIndicator)
advertIndicator.font = UIFont.systemFontOfSize(10.0)
advertIndicator.text = "Advertisement"
advertIndicator.textColor = UIColor.darkGrayColor()
advertIndicator.backgroundColor = UIColor(red: 252/255.0, green: 246/255.0, blue: 220/255.0, alpha: 1.0)
advertIndicator.clipsToBounds = true
advertIndicator.layer.masksToBounds = true
advertIndicator.layer.cornerRadius = 3
}
func layoutAdAssets(adObject: MPNativeAd!) {
adObject.loadTitleIntoLabel(titleLabel)
adObject.loadTextIntoLabel(mainTextLabel)
adObject.loadIconIntoImageView(iconImageView)
}
}
It's quite magical, really, that I forgot to add the subviews to the contentView of the NativeAdCell. self.contentView.addSubview(mainTextLabel) etc solves #2.
Not sure how to get this to work with IBOutlets still. It would be a lot easier that way (removes need for programmatic constraints).