How to merge one pdf into another pdf file in swift 3.0.? - pdf

I am using this code.but pdfDocumentRef3 coming nil. so its crashing.
Please let me know where i am doing wrong.
let cachesDirectoryPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0]
let filePath1 = "(cachesDirectoryPath)/ShowPdf_(self.airportMainId).pdf"
let filePath2 = "(cachesDirectoryPath)/ImagePdf_(self.airportMainId).pdf
let filePath3 = cachesDirectoryPath.appending("/Combine_(self.airportMainId).pdf")
self.mergeTwoPDF(filePath1: filePath1, filePath2: filePath2, combinePath: filePath3 )
func mergeTwoPDF(filePath1: String, filePath2: String, combinePath: String) {
let pdfURL1 = NSURL(fileURLWithPath: filePath1)
let pdfURL2 = NSURL(fileURLWithPath: filePath2)
let pdfURL3 = NSURL(fileURLWithPath: combinePath)
let pdfDocumentRef1 = CGPDFDocument(pdfURL1 as CFURL)
let pdfDocumentRef2 = CGPDFDocument(pdfURL2 as CFURL)
let pdfDocumentRef3 = CGPDFDocument(pdfURL3 as CFURL)
let numberOfPages1 = pdfDocumentRef1!.numberOfPages
let numberOfPages2 = pdfDocumentRef2!.numberOfPages
let writeContext = CGContext(pdfDocumentRef3 as! CFURL, mediaBox: nil, nil)
var page: CGPDFPage?
var mediaBox: CGRect
for var i in 0..<numberOfPages1 {
page = pdfDocumentRef1!.page(at: i)
mediaBox = page!.getBoxRect(.mediaBox)
writeContext!.beginPage(mediaBox: &mediaBox)
writeContext!.drawPDFPage(page!)
writeContext!.endPage()
}
for var i in 0..<numberOfPages2 {
page = pdfDocumentRef2!.page(at: i)
mediaBox = page!.getBoxRect(.mediaBox)
writeContext!.beginPage(mediaBox: &mediaBox)
writeContext!.drawPDFPage(page!)
writeContext!.endPage()
}
writeContext!.closePDF();
}

pdfDocumentRef3 is nil because the file does not exist.
You should use:
UIGraphicsBeginPDFContextToFile(combinePath, CGRect.zero, nil)
let writeContext = UIGraphicsGetCurrentContext()

Related

async image in SwiftUI

I am working on an api, in which i retrieve the texts but the image from the api is not showing inside the view. I have given it an async image. The async image shows as a grey part in the view. Please let me know what is missing here. It would be great if someone would help me out with this.
API modal as:
struct priceRange: Codable {
let status: String
let record: Record
}
struct Record: Codable {
let propertytype: [Property]
let placetype: [Place]
let floorplan: [Floor]
let amenity: [Amenity]
let path: String
}
struct Property: Codable {
let type: String
let image: String
let status: String
let id: Int
}
My network code goes here:
class PRViewModel: ObservableObject {
#Published var floors = [Floor]()
#Published var place = [Place]()
#Published var prop = [Property]()
#Published var res = [Amenity]()
#Published private(set) var exp: priceRange?
#Published private(set) var rec: Record?
func loadData(){
guard let url = URL(string: PR_data) else {
print("Invalid URL")
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) {(data, response, error) in
do {
if let todoData = data {
let decodedData = try JSONDecoder().decode(priceRange.self, from: todoData)
DispatchQueue.main.async {
self.res = decodedData.record.amenity
self.prop = decodedData.record.propertytype
self.floors = decodedData.record.floorplan
self.place = decodedData.record.placetype
print(decodedData.status)
//print(decodedData.record.path!)
}
} else {
print("No data")
}
} catch {
print(error)
}
}.resume()
}
}
List code goes here :
struct Price_range: View {
#StateObject var viewModel = PRViewModel()
var body: some View {
List(viewModel.prop, id: \.type) { item in
Text(item.type)
AsyncImage(url: URL(string: PR_URL + (viewModel.rec?.path ?? "") + "/" + item.image))
}
.onAppear {
viewModel.loadData()
}
}
}
Edit:
AsyncImage(url: URL(string: PR_URL + (viewModel.exp?.record.path ?? "") + "/" + item.image))
it still remains the same. I want to bring that “path” variable in the “record” modal to the view?
As allready pointed out in the comments you never assign any value to exp and res so they stay nil. You could assign them while you assign your previous properties:
do {
if let todoData = data {
let decodedData = try JSONDecoder().decode(priceRange.self, from: todoData)
DispatchQueue.main.async {
self.exp = decodedData // this
self.rec = decodedData.record // and this
self.res = decodedData.record.amenity
self.prop = decodedData.record.propertytype
self.floors = decodedData.record.floorplan
self.place = decodedData.record.placetype
print(decodedData.status)
//print(decodedData.record.path!)
}
} else {
print("No data")
}
} catch {
print(error)
}
and then do:
AsyncImage(url: URL(string: PR_URL + (viewModel.rec?.path ?? "") + "/" + item.image))
if there is still an issue try to verify your link is valid by using:
let _ = print(PR_URL + (viewModel.rec?.path ?? "") + "/" + item.image)
right before the line with the AsyncImage.

The operation couldn’t be completed. (com.amazonaws.AWSS3ErrorDomain error 0.)

When I am uploading video frames in my app it throws an error. I copied the code here, Can anyone please help me to overcome the error?
let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL: URL = directoryURL.appendingPathComponent("test.h264")
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast1,
identityPoolId:"us-east-1:5338ad28-9e8f-4347-a150-cabb7bc96ff7")
let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
s3Url = AWSS3.default().configuration.endpoint.url
let key = "test.h264"
let request = AWSS3TransferManagerUploadRequest()!
request.bucket = "skilai"
request.key = key
request.body = fileURL
request.acl = .publicReadWrite
request.contentType = "test/h264"
let transferManager = AWSS3TransferManager.default()
transferManager.upload(request).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
if let error = task.error
{
print("AWS Upload error \(error.localizedDescription)")
}
if task.result != nil
{
print("Uploaded \(key)")
let contentUrl = self.s3Url.appendingPathComponent("skilai").appendingPathComponent(key)
self.contentUrl = contentUrl
}
return nil
}

Bad Request: there is no photo in the request

I'm trying to send an image from my application to telegram bot like here
https://newfivefour.com/swift-form-data-multipart-upload-URLRequest.html
Here is the code
let BotToken = "12345"
let ChatID = "123"
func SendToTelegram()
{
var request = URLRequest(url: URL(string: "https://api.telegram.org/bot"+BotToken+"/sendPhoto")!)
request.httpMethod = "POST"
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let params = [:] as [String: String]
UIGraphicsBeginImageContextWithOptions(ScreenImage.bounds.size, true, 0.0)
ScreenImage.image?.draw(in: CGRect(x: 0, y: 0, width: ScreenImage.frame.size.width, height: ScreenImage.frame.size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
request.httpBody = createBody(parameters: params,
boundary: boundary,
data: UIImageJPEGRepresentation(image!, 0.7)!,
mimeType: "image/jpg",
filename: "hello.jpg")
print(request.httpBody!)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
return
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? AnyObject
if let parseJSON = json {
print("resp :\(parseJSON)")
}
} catch let error as NSError {
print("error : \(error)")
}
}
task.resume()
}
and get an error
Bad Request: there is no photo in the request";
"error_code" = 400;
ok = 0;
Where do i make a mistake? I'm new in SWIFT and sorry for my English
I know this question is old but the link provided pushed me in the right direction. This is my solution for server side Swift not iOS but you should be able to use it with minimal changes. Remember if you're using iOS, perform none of these operations on the main thread.
class NetworkManager {
func sendTelegramPhoto(_ photo: Data) {
let url = "https://api.telegram.org/bot\(Constants.Telegram.token)/sendPhoto"
let params: [String: Any] = [
"chat_id": Constants.Telegram.uid,
"photo": photo
]
let _ = sendMultiTypePostRequest(url, parameters: params)
}
private func sendMultiTypePostRequest(_ url: String, parameters: [String:String]) -> NetworkResponse {
var networkResponse = NetworkResponse()
let semaphore = DispatchSemaphore(value: 0)
guard let url = URL(string: url) else {
return networkResponse
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let boundary = "Boundary-\(UUID().uuidString)"
urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let httpBody = createBody(parameters: parameters,
boundary: boundary,
mimeType: "image/jpeg",
filename: "snapshot.jpg")
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
let session = URLSession(configuration: config)
let task = session.uploadTask(with: urlRequest, from: httpBody) { (data, response, error) in
networkResponse.data = data
networkResponse.response = response
networkResponse.error = error
semaphore.signal()
}
task.resume()
_ = semaphore.wait(timeout: .distantFuture)
return networkResponse
}
private func createBody(parameters: [String: String],
boundary: String,
mimeType: String,
filename: String) -> Data {
var body = Data()
let boundaryPrefix = "--\(boundary)\r\n"
for (key, value) in parameters {
if let data = value as? Data {
body.appendString(boundaryPrefix)
body.appendString("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimeType)\r\n\r\n")
body.append(data)
body.appendString("\r\n")
} else if let string = value as? String {
body.appendString(boundaryPrefix)
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(string)\r\n")
}
}
body.appendString("--".appending(boundary.appending("--")))
return body
}
}
private extension Data {
mutating func appendString(_ string: String) {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: false)
append(data!)
}
}

How to access the media library with Swift code?

I have to display a title of the song which I was selected I get the title(No need to play the song in the music library).What my question is I want to send song I was selected(Encoded) to PHP server..To display the song in a table view from the server and play the song...I want to find the correct path for iTunes music library so that I can encode easily.
func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
do {
// Get the directory contents urls (including subfolders urls)
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL( documentsUrl, includingPropertiesForKeys: nil, options: [])
let mp3Files = directoryContents.filter{ $0.pathExtension == "m4a" }
let mp3FileNames = mp3Files.flatMap({$0.URLByDeletingPathExtension?.lastPathComponent})
} catch let error as NSError {
}
let name = "/aFileName"
var filePath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first
print("\nfilePath: \(filePath)")
filePath = filePath!.stringByAppendingString(name)
print("\nfilePath: \(filePath)")
var filePathURL = NSURL.fileURLWithPath(filePath!)
print("\nfilePathURL: \(filePathURL)")
let item: MPMediaItem = mediaItemCollection.items[0]
print(item)
exportFiles = (item.valueForProperty(MPMediaItemPropertyAssetURL) as? NSURL)!
print(exportFiles)
// Export the ipod library as .m4a file to local directory for remote upload
let exportSession = AVAssetExportSession(asset: AVAsset(URL: exportFiles), presetName: AVAssetExportPresetAppleM4A)
print(exportFiles)
exportSession?.shouldOptimizeForNetworkUse = true
print(exportSession)
playingMusictitle = item.valueForProperty(MPMediaItemPropertyTitle) as? String ?? "Now Playing..."
print("\(exportFiles), title : \(title) ")
let str = exportFiles.absoluteString
let str2 = str!.stringByReplacingOccurrencesOfString("ipod-library://item/item", withString: "")
print(str2)
let arr = str2.componentsSeparatedByString("?")
mimeType = mimeType1.stringByReplacingOccurrencesOfString("id=", withString: "")
let path = item.valueForProperty(MPMediaItemPropertyLyrics) as? String ?? ""
print(path)
exportSession?.outputFileType = AVFileTypeAppleM4A
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let format = NSDateFormatter()
format.dateFormat="yyyy-MM-dd-HH-mm-ss"
audioname = "\(playingMusictitle)-\(format.stringFromDate(NSDate())).m4a"
print(audioname)
let documentsDirectoryy = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
self.soundFileURL = documentsDirectoryy.URLByAppendingPathComponent(audioname)
if NSFileManager.defaultManager().fileExistsAtPath(soundFileURL.absoluteString!) {
// probably won't happen. want to do something about it?
print("soundfile \(soundFileURL.absoluteString) exists")
}
Due to copyright protection you can only play songs from music library. You can't access row audio file!.I guess

AVMutableVideoComposition sometimes won't play video

I'm using this short snippet to set up my video. For some unknown reason - sometimes the video simply won't show up, while for other video it'll work perfectly.
let videoTrack: AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
let composition: AVMutableComposition = AVMutableComposition()
let videoComposition: AVMutableVideoComposition = AVMutableVideoComposition()
var videoSize: CGSize = videoTrack.naturalSize
let isPortrait_: Bool = self.isVideoPortrait(asset)
if isPortrait_ {
NSLog("video is portrait ")
videoSize = CGSizeMake(videoSize.height, videoSize.width)
}
composition.naturalSize = videoSize
videoComposition.renderSize = videoSize
// videoComposition.renderSize = videoTrack.naturalSize; //
videoComposition.frameDuration = CMTimeMake(1, 30)
let compositionVideoTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: 1)
let timeRange = videoTrack.timeRange
do {
try compositionVideoTrack.insertTimeRange(timeRange, ofTrack: videoTrack, atTime: kCMTimeZero)
} catch {
print("error")
}
let layerInst = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
layerInst.setTransform(videoTrack.preferredTransform, atTime: kCMTimeZero)
let inst: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
inst.timeRange = timeRange
inst.layerInstructions = [layerInst]
videoComposition.instructions = [inst]
let playerItem = AVPlayerItem(asset: composition)
playerItem.videoComposition = videoComposition
Tho for some videos, it simply wont show them up.
Any suggestions? Thanks!!
Hello i had a relative similar code hope this helps you figure out your problem
class func MergeVideosSequentially(URLS : [NSURL], callback : (error : ErrorType? , outURL : NSURL?) -> Void){
let composition = AVMutableComposition()
//videoTrack
let videoTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
let audioTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
var cursorTime = kCMTimeZero
for URL in URLS {
let asset = AVAsset(URL: URL)
let assetVideoTrack = asset.tracksWithMediaType(AVMediaTypeVideo).first! as AVAssetTrack
let assetAudioTrack = asset.tracksWithMediaType(AVMediaTypeAudio).first! as AVAssetTrack
var duration : CMTimeRange? = nil
duration = CMTimeRangeMake(kCMTimeZero, asset.duration)
do {
try videoTrack.insertTimeRange(duration!, ofTrack: assetVideoTrack, atTime: cursorTime)
try audioTrack.insertTimeRange(duration!, ofTrack: assetAudioTrack, atTime: cursorTime)
}catch {
print(error)
}
cursorTime = CMTimeAdd(cursorTime, asset.duration)
}
let directory = NSTemporaryDirectory()
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .LongStyle
dateFormatter.timeStyle = .ShortStyle
let date = dateFormatter.stringFromDate(NSDate())
let savePath = "\(directory)/mergedVideo-\(date).mp4"
let url = NSURL(fileURLWithPath: savePath)
let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)
exporter!.outputURL = url
exporter!.shouldOptimizeForNetworkUse = true
exporter!.outputFileType = AVFileTypeMPEG4
exporter!.exportAsynchronouslyWithCompletionHandler({ () -> Void in
let outputURL = exporter!.outputURL
switch exporter!.status {
case .Completed :
dispatch_async(dispatch_get_main_queue(), { () -> Void in
callback(error: nil, outURL: outputURL)
})
default:
callback(error: CCMovieWriterError.CannotMergeClips, outURL: nil)
}
})
}