I am doing some task to apply filter effect in to my WebRTC call, follow this tutorial:
https://developer.apple.com/documentation/vision/applying_matte_effects_to_people_in_images_and_video
Here is my code to convert:
func capturer(_ capturer: RTCVideoCapturer, didCapture frame: RTCVideoFrame) {
let pixelBufferr = frame.buffer as! RTCCVPixelBuffer
let pixelBufferRef = pixelBufferr.pixelBuffer
if #available(iOS 15.0, *) {
DispatchQueue.global().async {
if let output = GreetingProcessor.shared.processVideoFrame(
foreground: pixelBufferRef,
background: self.vbImage) {
print("new output: \(output) => \(output.pixelBuffer) + \(self.buffer(from: output))")
guard let px = output.pixelBuffer else { return }
let rtcPixelBuffer = RTCCVPixelBuffer(pixelBuffer: px)
let i420buffer = rtcPixelBuffer.toI420()
let newFrame = RTCVideoFrame(buffer: i420buffer, rotation: frame.rotation, timeStampNs: frame.timeStampNs)
self.videoSource.capturer(capturer, didCapture: newFrame)
}
}
}
}
THen here is how I apply effect:
func blendImages(
background: CIImage,
foreground: CIImage,
mask: CIImage,
isRedMask: Bool = false
) -> CIImage? {
// scale mask
let maskScaleX = foreground.extent.width / mask.extent.width
let maskScaleY = foreground.extent.height / mask.extent.height
let maskScaled = mask.transformed(by: __CGAffineTransformMake(maskScaleX, 0, 0, maskScaleY, 0, 0))
// scale background
let backgroundScaleX = (foreground.extent.width / background.extent.width)
let backgroundScaleY = (foreground.extent.height / background.extent.height)
let backgroundScaled = background.transformed(
by: __CGAffineTransformMake(backgroundScaleX, 0, 0, backgroundScaleY, 0, 0))
let blendFilter = isRedMask ? CIFilter.blendWithRedMask() : CIFilter.blendWithMask()
blendFilter.inputImage = foreground
blendFilter.backgroundImage = backgroundScaled
blendFilter.maskImage = maskScaled
return blendFilter.outputImage
}
The problem is output.pixelBuffer always nil, so I can not create RTCFrame to pass it again to delegate
Can someone help?
I have tried the following code:
windowNumber is CGWindowID
func screenshot(imgOption:CGWindowImageOption = .bestResolution ) -> NSImage {
guard let winNumber = self.windowNumber else { return NSImage( size: NSSize(width: 1, height: 1)) }
let inf = CGFloat(FP_INFINITE)
let null = CGRect(x: inf, y: inf, width: 0, height: 0)
let cgImage = CGWindowListCreateImage(null, .optionIncludingWindow, CGWindowID(winNumber), imgOption)
//cgImage == nil
guard let cgImageUnwrapped = cgImage else { return NSImage() }
let image = NSImage(cgImage: cgImageUnwrapped, size: self.frame.value.size )
return image
}
but with the following code I have a nil result in case of window is hidden.
I want to create multipage PDF of self.view. I have following viewController with tableView now I want to create the pdf of the view.
This is what I have done but it's create single page pdf only
func pdfDataWithTableView(tableView: UITableView) {
let priorBounds = tableView.bounds
let fittedSize = tableView.sizeThatFits(CGSize(width:priorBounds.size.width, height:tableView.contentSize.height))
tableView.bounds = CGRect(x:0, y:0, width:fittedSize.width, height:fittedSize.height)
let pdfPageBounds = CGRect(x:0, y:0, width:tableView.frame.width, height:self.view.frame.height)
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds,nil)
var pageOriginY: CGFloat = 0
while pageOriginY < fittedSize.height {
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil)
UIGraphicsGetCurrentContext()!.saveGState()
UIGraphicsGetCurrentContext()!.translateBy(x: 0, y: -pageOriginY)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
UIGraphicsGetCurrentContext()!.restoreGState()
pageOriginY += pdfPageBounds.size.height
}
UIGraphicsEndPDFContext()
tableView.bounds = priorBounds
var docURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
docURL = docURL.appendingPathComponent("myPassBook.pdf")
pdfData.write(to: docURL as URL, atomically: true)
share()
}
On save Button Call Below function
func createImg() -> UIImage {
guard tblView.numberOfSections > 0, tblView.numberOfRows(inSection: 0) > 0 else {
let errorImage = UIImage(named: "Error Image")
return errorImage!
}
UIGraphicsBeginImageContextWithOptions(CGSize(width: tblView.contentSize.width, height: tblView.contentSize.height), false, 0.0)
let context = UIGraphicsGetCurrentContext()
let previousFrame = tblView.frame
tblView.frame = CGRect(x: tblView.frame.origin.x, y: tblView.frame.origin.y, width: tblView.contentSize.width, height: tblView.contentSize.height)
// Draw view in that context
tblView.layer.render(in: context!)
tblView.frame = previousFrame
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
createPDFDataFromImage(image: image)
return image;
}
Create PDF from image and Share
func createPDFDataFromImage(image: UIImage){
let pdfData = NSMutableData()
let imgView = UIImageView.init(image: image)
let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
UIGraphicsBeginPDFContextToData(pdfData, imageRect, nil)
UIGraphicsBeginPDFPage()
let context = UIGraphicsGetCurrentContext()
imgView.layer.render(in: context!)
UIGraphicsEndPDFContext()
//try saving in doc dir to confirm:
let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
let path = dir?.appendingPathComponent("file.pdf")
do {
try pdfData.write(to: path!, options: NSData.WritingOptions.atomic)
} catch {
print("error catched")
}
let activityViewController = UIActivityViewController(activityItems: [pdfData] , applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)
}
I have been trying to simply overlay text onto a current PDF document that is essentially a timecard. I copy the file to the downloads folder and that works fine, but then when I try to use a CGContext to add text, it exports a white PDF document. Can anyone see where I'm going wrong?
do {
try fileManager.copyItem(at: pdfURL!, to: destinationURL)
} catch let error as NSError {
print("Copy failed :( with error: \(error)")
}
if let pdf: CGPDFDocument = CGPDFDocument(destinationURL as CFURL) { // Create a PDF Document
if pdf.numberOfPages == 1 {
let pdfPage: CGPDFPage = pdf.page(at: 1)!
let pageRect = pdfPage.getBoxRect(CGPDFBox.mediaBox)
//print(pageRect)
let context = CGContext.init(destinationURL as CFURL, mediaBox: nil, nil)
let font = NSFont(name: "Helvetica Bold", size: 20.0)
let textRect = CGRect(x: 250, y: 250, width: 500, height: 40)
let paragraphStyle: NSParagraphStyle = NSParagraphStyle.default
let textColor = NSColor.black
let textFontAttributes = [
NSAttributedStringKey.font: font!,
NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.paragraphStyle: paragraphStyle
]
let text: NSString = "Hello world"
text.draw(in: textRect, withAttributes: textFontAttributes)
context?.addRect(textRect)
context?.closePDF()
}
}
The following code is what I used to overlay text on macOS. I've been trying to find a link to the source answer I got this from. If I find it I'll edit this answer with a link.
// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
// Create a document, get the first page, and set the size of the page
let page: PDFPage = doc.page(at: 0)!
var mediaBox: CGRect = CGRect(x: 0, y: 0, width: 792, height: 612)
// This is where the magic happens. Create the drawing context on the PDF
let context = CGContext(dstURL as CFURL, mediaBox: &mediaBox, nil)
let graphicsContext = NSGraphicsContext(cgContext: context!, flipped: false)
NSGraphicsContext.current = graphicsContext
context!.beginPDFPage(nil)
// Draws the PDF into the context
page.draw(with: .mediaBox, to: context!)
// Parse and Draw Text on the context
drawText()
context!.saveGState()
context!.restoreGState()
context!.endPDFPage()
NSGraphicsContext.current = nil
context?.closePDF()
}
I was originally wanting to know how to make something like this
UIColor.myCustomGreen
so that I could define my own colors and use them throughout my app.
I had studied extensions before and I thought that I could probably use them to solve my problem, but I couldn't remember exactly how to set extensions up. Searching on Google at the time of this writing for "Swift extension" resulted in the documentation, several long tutorials, and a rather unhelpful Stack Overflow question.
So the answers are out there, but it takes some digging through the docs and tutorials. I decided to write this question and the following answer to add some better search keywords to Stack Overflow and to provide a quick refresher on how extensions are set up.
Specifically I wanted to know:
Where do the extensions reside (file and naming convention)?
What is the extension syntax?
What are a few simple common use examples?
Creating an extension
Add a new swift file with File > New > File... > iOS > Source > Swift File. You can call it what you want.
The general naming convention is to call it TypeName+NewFunctionality.swift.
Example 1 - Double
Double+Conversions.swift
import Swift // or Foundation
extension Double {
func celsiusToFahrenheit() -> Double {
return self * 9 / 5 + 32
}
func fahrenheitToCelsius() -> Double {
return (self - 32) * 5 / 9
}
}
Usage:
let boilingPointCelsius = 100.0
let boilingPointFarenheit = boilingPointCelsius.celsiusToFahrenheit()
print(boilingPointFarenheit) // 212.0
Example 2 - String
String+Shortcuts.swift
import Swift // or Foundation
extension String {
func replace(target: String, withString: String) -> String {
return self.replacingOccurrences(of: target, with: withString)
}
}
Usage:
let newString = "the old bike".replace(target: "old", withString: "new")
print(newString) // "the new bike"
Here are some more common String extensions.
Example 3 - UIColor
UIColor+CustomColor.swift
import UIKit
extension UIColor {
class var customGreen: UIColor {
let darkGreen = 0x008110
return UIColor.rgb(fromHex: darkGreen)
}
class func rgb(fromHex: Int) -> UIColor {
let red = CGFloat((fromHex & 0xFF0000) >> 16) / 0xFF
let green = CGFloat((fromHex & 0x00FF00) >> 8) / 0xFF
let blue = CGFloat(fromHex & 0x0000FF) / 0xFF
let alpha = CGFloat(1.0)
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
}
}
See here also.
Usage:
view.backgroundColor = UIColor.customGreen
Notes
Once you define an extension it can be used anywhere in your app just like the built in class functions.
If you are not sure of exactly what the function or property syntax should look like, you can Option+click a similar built in method. For example, when I Option+clicked UIColor.greenColor I see the declaration is class func greenColor() -> UIColor. That gives me a good clue for how to set up my custom method.
Apple Documentation for Extensions
In Objective-C extensions are known as categories.
Try this some new extension methods:
UIColor
extension UIColor{
//get new color from rgb value
class func RGB(_ red:CGFloat , andGreenColor green:CGFloat, andBlueColor blue:CGFloat, withAlpha alpha:CGFloat) -> UIColor
{
let color = UIColor(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
return color
}
}
//return color from comma separated string of RGB paramater
convenience init(rgbString :String, alpha:CGFloat = 1.0){
let arrColor = rgbString.components(separatedBy: ",")
let red:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[0])!)
let green:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[1])!)
let blue:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[2])!)
self.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
}
//return color from hexadecimal value
//let color2 = UIColor(rgbHexaValue: 0xFFFFFFFF)
convenience init(rgbHexaValue: Int, alpha: CGFloat = 1.0) {
self.init(red: CGFloat((rgbHexaValue >> 16) & 0xFF), green: CGFloat((rgbHexaValue >> 8) & 0xFF), blue: CGFloat(rgbHexaValue & 0xFF), alpha: alpha)
}
}
UITextField
extension UITextField{
//set cornerRadius
func cornerRadius(){
self.layoutIfNeeded()
self.layer.cornerRadius = self.frame.height / 2
self.clipsToBounds = true
}
//set bordercolor
func borderColor(){
self.layer.borderColor = TEXTFIELD_BORDER_COLOR.cgColor
self.layer.borderWidth = 1.0
}
//set borderWidth
func borderWidth(size:CGFloat){
self.layer.borderWidth = size
}
//check textfield is blank
func blank() -> Bool{
let strTrimmed = self.text!.trim()//get trimmed string
if(strTrimmed.characters.count == 0)//check textfield is nil or not ,if nil then return false
{
return true
}
return false
}
//set begginning space - left space
func setLeftPadding(paddingValue:CGFloat) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: paddingValue, height: self.frame.size.height))
self.leftViewMode = .always
self.leftView = paddingView
}
//set end of space
func setRightPadding(paddingValue:CGFloat){
let paddingView = UIView(frame: CGRect(x: (self.frame.size.width - paddingValue), y: 0, width: paddingValue, height: self.frame.size.height))
self.rightViewMode = .always
self.rightView = paddingView
}
}
UIFont
extension UIFont{
// Returns a scaled version of UIFont
func scaled(scaleFactor: CGFloat) -> UIFont {
let newDescriptor = fontDescriptor.withSize(fontDescriptor.pointSize * scaleFactor)
return UIFont(descriptor: newDescriptor, size: 0)
}
}
UIImage
public enum ImageFormat {
case PNG
case JPEG(CGFloat)
}
extension UIImage {
//convert image to base64 string
func toBase64() -> String {
var imageData: NSData
switch format {
case .PNG: imageData = UIImagePNGRepresentation(self)! as NSData
case .JPEG(let compression): imageData = UIImageJPEGRepresentation(self, compression)! as NSData
}
return imageData.base64EncodedString(options: .lineLength64Characters)
}
//convert string to image
class func base64ToImage(toImage strEncodeData: String) -> UIImage {
let dataDecoded = NSData(base64Encoded: strEncodeData, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
let image = UIImage(data: dataDecoded as Data)
return image!
}
//Function for store file/Image into local directory. If image is already on the directory then first remove it and replace new image/File on that location
func storedFileIntoLocal(strImageName:String) -> String{
var strPath = ""
let documentDirectory1 = NSString.init(string: String.documentDirectory())
let imageName:String = strImageName + ".png"
let imagePath = documentDirectory1.appendingPathComponent(imageName)
strPath = imagePath
let fileManager = FileManager.default
let isExist = fileManager.fileExists(atPath: String.init(imagePath))
if(isExist == true)
{
do {
try fileManager.removeItem(atPath: imagePath as String)//removing file if exist
// print("Remove success")
} catch {
print(error)
}
}
let imageData:Data = UIImageJPEGRepresentation(self, 0.5)!
do {
try imageData.write(to: URL(fileURLWithPath: imagePath as String), options: .atomic)
} catch {
print(error)
strPath = "Failed to cache image data to disk"
return strPath
}
return strPath
}
//function for resize image
func resizeImage(targetSize: CGSize) -> UIImage {
let size = self.size
let widthRatio = targetSize.width / self.size.width
let heightRatio = targetSize.height / self.size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
// newSize = size
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
Date
let YYYY_MM_DD_HH_MM_SS_zzzz = "yyyy-MM-dd HH:mm:ss +zzzz"
let YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"
let DD_MM_YYYY = "dd-MM-yyyy"
let MM_DD_YYYY = "MM-dd-yyyy"
let YYYY_DD_MM = "yyyy-dd-MM"
let YYYY_MM_DD_T_HH_MM_SS = "yyyy-MM-dd'T'HH:mm:ss"
extension Date{
//convert string to date
static func convertStringToDate(strDate:String, dateFormate strFormate:String) -> Date{
let dateFormate = DateFormatter()
dateFormate.dateFormat = strFormate
dateFormate.timeZone = TimeZone.init(abbreviation: "UTC")
let dateResult:Date = dateFormate.date(from: strDate)!
return dateResult
}
//Function for old date format to new format from UTC to local
static func convertDateUTCToLocal(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
let dateFormatterUTC:DateFormatter = DateFormatter()
dateFormatterUTC.timeZone = NSTimeZone(abbreviation: "UTC") as TimeZone!//set UTC timeZone
dateFormatterUTC.dateFormat = strOldFormate //set old Format
if let oldDate:Date = dateFormatterUTC.date(from: strDate) as Date?//convert date from input string
{
dateFormatterUTC.timeZone = NSTimeZone.local//set localtimeZone
dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
if let strNewDate:String = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
{
return strNewDate
}
return strDate
}
return strDate
}
//Convert without UTC to local
static func convertDateToLocal(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
let dateFormatterUTC:DateFormatter = DateFormatter()
//set local timeZone
dateFormatterUTC.dateFormat = strOldFormate //set old Format
if let oldDate:Date = dateFormatterUTC.date(from: strDate) as Date?//convert date from input string
{
dateFormatterUTC.timeZone = NSTimeZone.local
dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
if let strNewDate = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
{
return strNewDate
}
return strDate
}
return strDate
}
//Convert Date to String
func convertDateToString(strDateFormate:String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = strDateFormate
let strDate = dateFormatter.string(from: self)
// dateFormatter = nil
return strDate
}
//Convert local to utc
static func convertLocalToUTC(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
let dateFormatterUTC:DateFormatter = DateFormatter()
dateFormatterUTC.timeZone = NSTimeZone.local as TimeZone!//set UTC timeZone
dateFormatterUTC.dateFormat = strOldFormate //set old Format
if let oldDate:Date = dateFormatterUTC.date(from: strDate) as Date?//convert date from input string
{
dateFormatterUTC.timeZone = NSTimeZone.init(abbreviation: "UTC")! as TimeZone//set localtimeZone
dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
if let strNewDate:String = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
{
return strNewDate
}
return strDate
}
return strDate
}
//Comparison two date
static func compare(date:Date, compareDate:Date) -> String{
var strDateMessage:String = ""
let result:ComparisonResult = date.compare(compareDate)
switch result {
case .orderedAscending:
strDateMessage = "Future Date"
break
case .orderedDescending:
strDateMessage = "Past Date"
break
case .orderedSame:
strDateMessage = "Same Date"
break
default:
strDateMessage = "Error Date"
break
}
return strDateMessage
}
}
Calling this functions:
let color1 = UIColor.RGB(100.0, andGreenColor: 200.0, andBlueColor: 300.0, withAlpha: 1.0)
let color2 = UIColor.init(rgbHexaValue: 800000, alpha: 1.0)
let color3 = UIColor.init(rgbString: ("100.0,200.0,300.0", alpha: 1.0)
self.txtOutlet.cornerRadius()
self.txtOutlet.borderColor()
self.txtOutlet.setLeftPadding(paddingValue: 20.0)
self.txtOutlet.setRightPadding(paddingValue: 20.0)
let yourScaledFont = self.dependentView.font.scaled(scaleFactor: n as! CGFloat)
let base64String = (image?.toBase64(format: ImageFormat.PNG))!
let resultImage = UIImage.base64ToImage(toImage: base64String)
let path = yourImage.storedFileIntoLocal(strImageName: "imagename")
Swift 3.0 example:
extension UITextField
{
func useUnderline() {
let border = CALayer()
let borderWidth = CGFloat(1.0)
border.borderColor = UIColor.lightGray.cgColor
border.frame = CGRect(origin: CGPoint(x: 0,y :self.frame.size.height - borderWidth), size: CGSize(width: self.frame.size.width, height: self.frame.size.height))
border.borderWidth = borderWidth
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
Underline text in UITextField
Used in function ViewDidLoad()
firstNametext.underlined(0.5)
Extension
extension UITextField {
func underlined(_ size:Double){
let border = CALayer()
let width = CGFloat(size)
border.borderColor = UIColor.red.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width,
width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true }
}
}
UIColor+util.swift
import UIKit
extension UIColor{
class func getCustomBlueColor() -> UIColor
{
return UIColor(red:0.043, green:0.576 ,blue:0.588 , alpha:1.00)
}
func getNameofColour() ->String
{
return "myOrange"
}
}
Usage :
NSLog("\(UIColor.getCustomBlueColor())")
let color=UIColor(red:0.043, green:0.576 ,blue:0.588 , alpha:1.00);
NSLog(color.getNameofColour())
I hope you see that what is difference . One of Function starting with class func another one starting only func . you can use which you like.
One of the best example of extension and convenience initializer :
extension UIActivityIndicatorView {
convenience init(activityIndicatorStyle: UIActivityIndicatorViewStyle, color: UIColor, placeInTheCenterOf parentView: UIView) {
self.init(activityIndicatorStyle: activityIndicatorStyle)
center = parentView.center
self.color = color
parentView.addSubview(self)
}
}
You can use it in following ways :
Initialize activityIndicator
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge, color: .gray, placeInTheCenterOf: view)
Start animating activity indicator
activityIndicator.startAnimating()
Stop animating activity indicator
activityIndicator.stopAnimating()
If you like to use a colour with a given tint like used in brand manuals:
Swift 4.2 + xcode 9.4.1.
extension UIColor {
func withTint(tint: CGFloat)->UIColor {
var tint = max(tint, 0)
tint = min(tint, 1)
/* Collect values of sender */
var r : CGFloat = 0
var g : CGFloat = 0
var b : CGFloat = 0
var a : CGFloat = 0
self.getRed(&r, green: &g, blue: &b, alpha: &a)
/* Calculate the tint */
r = r+(1-r)*(1-tint)
g = g+(1-g)*(1-tint)
b = b+(1-b)*(1-tint)
a = 1
return UIColor.init(red: r, green: g, blue: b, alpha: a)
}
}
In your code
let redWithTint = UIColor.red.withTint(tint: 0.4)
Here is an extension example of an eye catching animation effect that works with cells from UITableView. Each cell grows from a point source to normal size as you scroll a UITableView. Adjust the animation timing as desired.
Since each cell shows up with a little time stagger while scrolling, the effect ripples nicely! See this 15 second clip that showcases the effect : https://www.youtube.com/watch?v=BVeQpno56wU&feature=youtu.be
extension UITableViewCell {
func growCellDuringPresentation(thisCell : UITableViewCell) {
thisCell.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
UIView.animate(withDuration: TimeInterval(0.35), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction, animations: {
thisCell.transform = CGAffineTransform(scaleX: 1, y: 1)
}, completion: nil)
}
}
To use the extension you make a call to it just before the cell is returned in cellForRowAt, like shown below :
cell.growCellDuringPresentation(thisCell: cell)
return cell
Note this same method works when returning cells for a collection view.
Here is an extension that works exactly the same, except that it rotates the cells during presentation :
extension UITableViewCell {
func rotateCellDuringPresentation(thisCell : UITableViewCell) {
thisCell.transform = CGAffineTransform(rotationAngle: .pi)
UIView.animate(withDuration: TimeInterval(0.35), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction, animations: {
thisCell.transform = CGAffineTransform(rotationAngle: 0)
}, completion: nil)
}
}
It's called similarly :
cell.rotateCellDuringPresentation(thisCell: cell)
return cell
Here is an extension along the same lines that translates the cells in the X direction
extension UITableViewCell {
func translateCellDuringPresentation(thisCell : UITableViewCell) {
thisCell.layer.transform = CATransform3DMakeTranslation(-300, 0, 0)
UIView.animate(withDuration: TimeInterval(0.5), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction, animations: {
thisCell.layer.transform = CATransform3DMakeTranslation(0, 0, 0)
}, completion: nil)
}
}
It's called similarly :
cell.translateCellDuringPresentation(thisCell: cell)
return cell