UICollectionViewListCell is configured like so:
var configuration = cell.defaultContentConfiguration()
configuration.text = "Foo"
configuration.image = UIImage(named: "foo")
configuration.imageProperties.maximumSize = CGSize(width: 40, height: 40)
cell.contentConfiguration = configuration
How can I use Nuke to load the image from a URL? With UITableViewCell, we can do:
Nuke.loadImage(with: url, into: cell.imageView)
But UICollectionViewListCell does not have an imageView.
I did with kingfisher:
var content = cell.defaultContentConfiguration()
let image = UIImageView()
image.image = UIImage(named:"EmptyProfile.png")
if let url = URL(string: user.avatarURL) {
image.load(url: url)
}
content.image = image.image
cell.contentConfiguration = content
--
extension UIImageView {
func load(url: URL) {
self.kf.setImage(with: url)
}
}
Related
I want to keep the header in a UICollectionViewDiffableDataSource, as I understand I can do it with layout.sectionHeadersPinToVisibleBounds, but it's not usable with my collectionView layout
private func createLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { section, layoutEnvironment in
var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
config.headerMode = section == 0 ? .none : .firstItemInSection
config.backgroundColor = .darkGrayBackground
config.showsSeparators = false
let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
section.interGroupSpacing = 30
self.addHeader(to: section)
return section
}
}
private func addHeader(to section: NSCollectionLayoutSection) {
let headerFooterSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(20)
)
let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerFooterSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .top
)
section.boundarySupplementaryItems = [sectionHeader]
}
and
collectionView = UICollectionView(frame: bounds, collectionViewLayout: createLayout())
I even can't access to it via
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.sectionHeadersPinToVisibleBounds = true // never called
}
Could anyone help me on this? Thank you so much
I am anlysing live-images in a Capture-Session of Type AVMediaTypeVideo. How can I capture a high-quality-still image (not the low-resolution sample buffer), at certain events=
var videoCaptureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
var device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
var previewLayer: AVCaptureVideoPreviewLayer?
var captureSession = AVCaptureSession()
let cameraOutput = AVCapturePhotoOutput()
//called in view did load
private func setupCamera() {
let input = try? AVCaptureDeviceInput(device: videoCaptureDevice)
captureSession.sessionPreset = AVCaptureSessionPreset640x480
if self.captureSession.canAddInput(input) {
self.captureSession.addInput(input)
}
self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
let videoDataOutput = AVCaptureVideoDataOutput()
if self.captureSession.canAddOutput(videoDataOutput){
self.captureSession.addOutput(videoDataOutput)
videoDataOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
}
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
// sampleBuffer is analysed
// if result is positive, I would like to take a high quality picture
}
Here's a little snippet that I use in my apps. I hope this will be helpful
private func takePhoto() -> Void
{
if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo)
{
videoConnection.videoOrientation = AVCaptureVideoOrientation.portrait
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) in
guard let buffer = sampleBuffer else
{
return
}
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
let dataProvider = CGDataProvider(data: imageData as! CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!,
decode: nil,
shouldInterpolate: true,
intent: CGColorRenderingIntent.defaultIntent)
// The image taked
let image: UIImage = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.right)
// Detenemos la captura de imagenes
self.captureSession!.stopRunning()
})
}
}
If you don't set the sessionPreset property of your captureSession variable, by default his values is AVCaptureSessionPresetHigh. The only preset that is higher than this is AVCaptureSessionPresetPhoto
I tried a test-project. It worked but the method I used, put programmatically created labels over old existing labels. When the length of a string array is lower than the old one, it shows unnecessary old labels due to addSubview method.
How can I handle this problem?
import UIKit
extension UIView {
func pushTransition(duration:CFTimeInterval) {
let animation:CATransition = CATransition()
animation.timingFunction = CAMediaTimingFunction(name:
kCAMediaTimingFunctionEaseInEaseOut)
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromBottom
animation.duration = duration
self.layer.addAnimation(animation, forKey: kCATransitionPush)
}
}
class ViewController: UIViewController {
var current:Float = 125.24
var discount:Float = 1.212342748
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func doAction(sender: AnyObject) {
let currentstr = String(format: "₺%.2f", self.current)
let length = currentstr.characters.count
var strarray = Array(currentstr.characters)
strarray[length-3] = ","
print(strarray)
self.current = self.current-self.discount
let newcurrent = String(format: "₺%.2f", self.current)
let newcurrentlength = newcurrent.characters.count
var newcurrentarray = Array(newcurrent.characters)
newcurrentarray[newcurrentlength-3] = ","
print(newcurrentarray)
var labels = [UILabel]()
print(labels)
if (length == newcurrentlength) {
for i in 1 ..< length+1 {
labels.append(UILabel(frame: CGRectMake((15*CGFloat(i)), 100, 20, 20)))
if (strarray[i-1] == newcurrentarray[i-1]){
print("SAME")
labels[i-1].text = String(newcurrentarray[i-1])
labels[i-1].textAlignment = NSTextAlignment.Center
labels[i-1].backgroundColor = UIColor.redColor()
self.view.addSubview(labels[i-1])
} else {
print("CHANGED")
labels[i-1].pushTransition(0.4)
labels[i-1].text = String(newcurrentarray[i-1])
labels[i-1].textAlignment = NSTextAlignment.Center
labels[i-1].backgroundColor = UIColor.redColor()
self.view.addSubview(labels[i-1])
}
}
} else {
for i in 1..<newcurrentlength+1 {
labels.append(UILabel(frame: CGRectMake((15*CGFloat(i)), 100, 20, 20)))
if (strarray[i-1] == newcurrentarray[i-1]){
print("SAME")
labels[i-1].text = String(newcurrentarray[i-1])
labels[i-1].textAlignment = NSTextAlignment.Center
labels[i-1].backgroundColor = UIColor.redColor()
self.view.addSubview(labels[i-1])
} else {
print("CHANGED")
labels[i-1].pushTransition(0.4)
labels[i-1].text = String(newcurrentarray[i-1])
labels[i-1].textAlignment = NSTextAlignment.Center
labels[i-1].backgroundColor = UIColor.redColor()
self.view.addSubview(labels[i-1])
}
}
}
}
}
EDIT
I put label array out of action section and it's fixed.
var labels = [UILabel]()
However, the transition between 100,00 and 99,99 there is a problem with the last child of label array. It still shows last digit like 99,990
I'm saving an image using .writetofile but I don't know how to recover it.
This how I save the image:
self.pdfData.writeToURL(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.URLByAppendingPathComponent("testgogo.pdf"), atomically: true) // what it is saved as
self.pdfData.writeToFile("tessst.pdf", atomically: false)
print(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.path!)
var pdfData: NSData {
let result = NSMutableData()
UIGraphicsBeginPDFContextToData(result, frame, nil)
guard let context = UIGraphicsGetCurrentContext()
else { return result }
UIGraphicsBeginPDFPage()
layer.renderInContext(context)
UIGraphicsEndPDFContext()
return result
}
How can I fetch the image back later on ?
Here is an example of how you could do it in Swift 2.x.
It uses the NSData(contentsOfFile: myFilePath) to load the file.
The example uses a PNG file.
Directly from my Playground:
import UIKit
/*
* Creates an UIImage from a UIView
*/
func createImage(fromView view: UIView) -> UIImage {
UIGraphicsBeginImageContext(view.frame.size)
let context = UIGraphicsGetCurrentContext()
view.layer.renderInContext(context!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return image
}
/*
* Finds the path in Document folder
*/
func createMyFilePath(forFileName fileName: String) -> String? {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)
if let path = paths.first {
return path + "/\(fileName)"
}
return nil
}
/*
* Main behaviour
*/
// ImageView with Label on it
let imageView = UIImageView(image: UIImage(named: "borat"))
let label = UILabel(frame: imageView.frame)
label.font = UIFont(name: "helvetica", size: 40)
label.text = "Great Success!"
imageView .addSubview(label)
// Find the path where to save
guard let myFilePath = createMyFilePath(forFileName: "borat-with-label.png") else {
print("Cannot generate file path ☹️")
exit(0)
}
// Use this to check in finder where your file is saved
print(myFilePath)
// Transform the imageView in UIImage to save it
let imageToSave = createImage(fromView: imageView)
// Get the image as data
guard let imageToSaveAsData = UIImagePNGRepresentation(imageToSave) else {
print("Cannot transform image to data ☹️")
exit(1)
}
// Save to Disk!
do{
try imageToSaveAsData.writeToFile(myFilePath, options: .DataWritingAtomic)
} catch {
print("Error, cannot write to the location \(myFilePath)")
}
// Load from Disk!
let loadedImageData = NSData(contentsOfFile: myFilePath)
// Check the data is the same
if loadedImageData == imageToSaveAsData {
print("✌️")
}
// Have a look at the loaded image!
UIImage(data: loadedImageData!)
You will need to remember the URL where you saved the image/pdf that you are storing.
In order to get it back, you can use the NSData class to get the contents of the file at that url.
dataWithContentsOfURL:(NSURL *)aURL is a good place to start.
It looks like the problem might be that you are trying to load the pdf file as an image which won't work. Try this method:
if let pdfURL = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil),data = NSData(contentsOfURL: pdfURL), baseURL = pdfURL.URLByDeletingLastPathComponent {
let webView = UIWebView(frame: CGRectMake(20,20,self.view.frame.size.width-40,self.view.frame.size.height-40))
webView.loadData(data, MIMEType: "application/pdf", textEncodingName:"", baseURL: baseURL)
self.view.addSubview(webView)
}
Ps I got this code from here: How to Load Local PDF in UIWebView in Swift
Using a slightly modified version of the code in this other answer
I have the following code:
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
lazy var documentsPath = {
return NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
}()
let fileName = "file.pdf"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createPDF()
loadPDF()
}
func createPDF() {
let html = "<b>Hello <i>World!</i></b> <p>Generate PDF file from HTML in Swift</p>"
let fmt = UIMarkupTextPrintFormatter(markupText: html)
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(fmt, startingAtPageAtIndex: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
let printable = CGRectInset(page, 0, 0)
render.setValue(NSValue(CGRect: page), forKey: "paperRect")
render.setValue(NSValue(CGRect: printable), forKey: "printableRect")
// 4. Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil)
for i in 1...render.numberOfPages() {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPageAtIndex(i - 1, inRect: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
pdfData.writeToFile("\(documentsPath)/\(fileName)", atomically: true)
}
func loadPDF() {
let filePath = "\(documentsPath)/\(fileName)"
let url = NSURL(fileURLWithPath: filePath)
let urlRequest = NSURLRequest(URL: url)
webView.loadRequest(urlRequest)
}
}
This code works, it creates a PDF file and then loads the same PDF file into a webView. The only thing that I changed was to create a lazy variable that returns the documents directory and I use a constant for the file path.
You should be able to use the same methods to save and retrieve your PDF file.
Im trying to program a UIButton that performs that prints a message to the console. I can see the button and touch it but as soon as I touch it my app stops running and the console shows the following error:
Game[2743:63724] -[Game.GameScene buttonAction:]: unrecognized selector sent to instance 0x7a11ad00
2014-09-15 17:51:06.106 Game[2743:63724] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[GameGameScene buttonAction:]: unrecognized selector sent to instance 0x7a11ad00'
this is my code:
let imageButton = UIImage(named: "playbutton2") as UIImage
let buttonPlay = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
buttonPlay.frame = CGRectMake(screenSize.width / 2 , screenSize.height / 2, 100, 100)
buttonPlay.setImage(imageButton, forState: .Normal)
buttonPlay.addTarget(self, action: Selector("buttonAction:"), forControlEvents: UIControlEvents.TouchUpInside)
buttonPlay.tag = 22
self.view.addSubview(buttonPlay)
and
func buttonAction(sender:UIButton!) {
println("Button tapped")
}
------- COMPLETE CODE ---------
import SpriteKit
class GameScene: SKScene {
var skyColor = SKColor()
var bird = SKSpriteNode()
var moving = SKNode()
var titleLabelNode = SKLabelNode()
var title = NSString()
let imageButton = UIImage(named: "playbutton2") as UIImage
let screenSize: CGRect = UIScreen.mainScreen().bounds
override func didMoveToView(view: SKView) {
/* Setup your scene here */
self.addChild(moving)
skyColor = SKColor(red: 113.0/255.0, green: 197.0/255.0, blue: 207.0/255.0, alpha: 1.0)
self.backgroundColor = skyColor
var birdTexture1 = SKTexture(imageNamed: "Bird1")
birdTexture1.filteringMode = SKTextureFilteringMode.Nearest
var birdTexture2 = SKTexture(imageNamed: "Bird2")
birdTexture2.filteringMode = SKTextureFilteringMode.Nearest
var animation = SKAction.animateWithTextures([birdTexture1, birdTexture2], timePerFrame: 0.2)
var flap = SKAction.repeatActionForever(animation)
bird = SKSpriteNode(texture: birdTexture1)
bird.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame) + 150)
bird.runAction(flap)
bird.physicsBody = SKPhysicsBody(circleOfRadius: bird.size.height/2.0)
bird.physicsBody.dynamic = false
self.addChild(bird)
var groundTexture = SKTexture(imageNamed: "Ground")
groundTexture.filteringMode = SKTextureFilteringMode.Nearest
var moveGroundSprite = SKAction.moveByX(-groundTexture.size().width, y: 0, duration: NSTimeInterval(0.01 * groundTexture.size().width))
var resetGroundSprite = SKAction.moveByX(groundTexture.size().width, y: 0, duration: 0)
var moveGroundSpritesForever = SKAction.repeatActionForever(SKAction.sequence([moveGroundSprite, resetGroundSprite]))
for var i:CGFloat = 0; i<2 + self.frame.size.width / (groundTexture.size().width); ++i {
var sprite = SKSpriteNode(texture: groundTexture)
sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2)
sprite.runAction(moveGroundSpritesForever)
moving.addChild(sprite)
}
title = "Swing Bird"
titleLabelNode.fontName = "Helvetica-Bold"
titleLabelNode.fontSize = 80
//titleLabelNode.fontColor = SKColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.)
titleLabelNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 50)
titleLabelNode.text = "\(title)"
addChild(titleLabelNode)
let buttonPlay = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
buttonPlay.frame = CGRectMake(screenSize.width / 2 , screenSize.height / 2, 100, 100)
buttonPlay.setImage(imageButton, forState: .Normal)
buttonPlay.addTarget(self, action: Selector("buttonAction:"), forControlEvents: UIControlEvents.TouchUpInside)
buttonPlay.tag = 22
self.view.addSubview(buttonPlay)
func buttonAction(sender:UIButton!) {
println("Button tapped")
}
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Your function buttonAction is defined at the wrong level. It is currently a function inside didMoveToView instead of a function of the class GameScene.
You can fix it like this:
class GameScene: SKScene {
...
// Move the function here!
func buttonAction(sender:UIButton!) {
println("Button tapped")
}
override func didMoveToView(view: SKView) {
...