Post

Replies

Boosts

Views

Activity

How to share PHAsset with UIActivityViewController like Photos App?
I am building an app about photos and I want to create a photo sharing feature like Apple's Photos App. Please see Steps to Reproduce and attached project. The current share method has the following issues The file name of the shared photo changes to “FullSizeRender”. The creation and update dates of shared photos will change to the date they were edited or shared. I want to ensure that the following conditions are definitely met Share the latest edited version. The creation date should be when the original photo was first created. How can I improve the code? STEPS TO REPRODUCE class PHAssetShareManager { static func shareAssets(_ assets: [PHAsset], from viewController: UIViewController, sourceView: UIView) { let manager = PHAssetResourceManager.default() var filesToShare: [URL] = [] let group = DispatchGroup() for asset in assets { group.enter() getAssetFile(asset, resourceManager: manager) { fileURL in if let fileURL = fileURL { filesToShare.append(fileURL) } group.leave() } } group.notify(queue: .main) { self.presentShareSheet(filesToShare, from: viewController, sourceView: sourceView) } } private static func getAssetFile(_ asset: PHAsset, resourceManager: PHAssetResourceManager, completion: @escaping (URL?) -> Void) { print("getAssetFile") let resources: [PHAssetResource] switch asset.mediaType { case .image: if asset.mediaSubtypes.contains(.photoLive) { // let editedResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .fullSizePairedVideo } // let originalResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .pairedVideo } let editedResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .fullSizePhoto } let originalResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .photo } resources = editedResources.isEmpty ? originalResources : editedResources } else { let editedResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .fullSizePhoto } let originalResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .photo } resources = editedResources.isEmpty ? originalResources : editedResources } case .video: let editedResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .fullSizeVideo } let originalResources = PHAssetResource.assetResources(for: asset).filter { $0.type == .video } resources = editedResources.isEmpty ? originalResources : editedResources default: print("Unsupported media type") completion(nil) return } guard let resource = resources.first else { print("No resource found") completion(nil) return } let fileName = resource.originalFilename let tempDirectoryURL = FileManager.default.temporaryDirectory let localURL = tempDirectoryURL.appendingPathComponent(fileName) // Delete existing files and reset cache if FileManager.default.fileExists(atPath: localURL.path) { do { try FileManager.default.removeItem(at: localURL) } catch { print("Error removing existing file: \(error)") } } let options = PHAssetResourceRequestOptions() options.isNetworkAccessAllowed = true resourceManager.writeData(for: resource, toFile: localURL, options: options) { (error) in if let error = error { print("Error writing asset data: \(error)") completion(nil) } else { completion(localURL) } } } private static func presentShareSheet(_ items: [Any], from viewController: UIViewController, sourceView: UIView) { print("presentShareSheet") let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) if UIDevice.current.userInterfaceIdiom == .pad { activityViewController.popoverPresentationController?.sourceView = sourceView activityViewController.popoverPresentationController?.sourceRect = sourceView.bounds } viewController.present(activityViewController, animated: true, completion: nil) } }```
0
0
290
Oct ’24
PHPhotoLibrary.shared (). performChanges does not work. I want to make an app that rotates photos.
https://developer.apple.com/documentation/photokit/browsing_and_modifying_photo_albums I am thinking of making a photo editing application (photo rotation application) by referring to the sample project that can be downloaded from this URL. In this sample project, when I try to filter photos with sepia or chrome, some photos work and some do not work. When things don't work, usually run into errors like the one below. Can't edit the asset: Optional (Error Domain = NSCocoaErrorDomain Code = -1 "(null)") I don't even know the correlation between photos that succeed and photos that fail to edit. It's strange that Apple's genuine photo app can rotate all photos. Is the structure different from the genuine app? How can I successfully edit (filter and rotate) all kinds of photos based on this sample code? The code below is the code in the sample project. It seems that the image is generated using ".ciContext.writeJPEGRepresentation PHPhotoLibrary.shared().performChanges({ 														let request = PHAssetChangeRequest(for: self.asset) 														request.contentEditingOutput = output 												} Seems to be making changes to the photos stored in the library. Sample Project // Returns a filter-applier function for the named filter. 		// Use the function as a handler for a UIAlertAction object. 		/// - Tag: ApplyFilter 		func getFilter(_ filterName: String) -> (UIAlertAction) -> Void { 				func applyFilter(_: UIAlertAction) { 						// Set up a handler to handle prior edits. 						let options = PHContentEditingInputRequestOptions() 						options.canHandleAdjustmentData = { 								$0.formatIdentifier == self.formatIdentifier && $0.formatVersion == self.formatVersion 						} 						 						// Prepare for editing. 						asset.requestContentEditingInput(with: options, completionHandler: { input, info in 								guard let input = input 										else { fatalError("Can't get the content-editing input: \(info)") } 								 								// This handler executes on the main thread; dispatch to a background queue for processing. 								DispatchQueue.global(qos: .userInitiated).async { 										 										// Create adjustment data describing the edit. 										let adjustmentData = PHAdjustmentData(formatIdentifier: self.formatIdentifier, 																													formatVersion: self.formatVersion, 																													data: filterName.data(using: .utf8)!) 										 										// Create content editing output, write the adjustment data. 										let output = PHContentEditingOutput(contentEditingInput: input) 										output.adjustmentData = adjustmentData 										 										// Select a filtering function for the asset's media type. 										let applyFunc: (String, PHContentEditingInput, PHContentEditingOutput, @escaping () -> Void) -> Void 										if self.asset.mediaSubtypes.contains(.photoLive) { 												applyFunc = self.applyLivePhotoFilter 										} else if self.asset.mediaType == .image { 												applyFunc = self.applyPhotoFilter 										} else { 												applyFunc = self.applyVideoFilter 										} 										 										// Apply the filter. 										applyFunc(filterName, input, output, { 												// When the app finishes rendering the filtered result, commit the edit to the photo library. 												PHPhotoLibrary.shared().performChanges({ 														let request = PHAssetChangeRequest(for: self.asset) 														request.contentEditingOutput = output 												}, completionHandler: { success, error in 														if !success { print("Can't edit the asset: \(String(describing: error))") } 												}) 										}) 								} 						}) 				} 				return applyFilter 		} 		 		func applyPhotoFilter(_ filterName: String, input: PHContentEditingInput, output: PHContentEditingOutput, completion: () -> Void) { 				 				// Load the full-size image. 				guard let inputImage = CIImage(contentsOf: input.fullSizeImageURL!) 						else { fatalError("Can't load the input image to edit.") } 				 				//MARK:	Apply the filter and Rotation 				let outputImage = inputImage 						.oriented(forExifOrientation: input.fullSizeImageOrientation) 						.applyingFilter(filterName, parameters: [:]).oriented(.right) 				 				// Write the edited image as a JPEG. 				do { 						//MARK: I get errors here 						try self.ciContext.writeJPEGRepresentation(of: outputImage, 																											 to: output.renderedContentURL, colorSpace: inputImage.colorSpace!, options: [:]) 				} catch let error { 						fatalError("Can't apply the filter to the image: \(error).") 				} 				completion() 		} I would appreciate it if you could answer Thank you in advance.
0
0
724
Nov ’20
want to copy and move the app project from old Mac to new Mac.
HelloI switched to a new Mac recently.I have already submitted the app to the App Store and I have the app in the App Store.I want to copy and move the app project from my old Mac to my new Mac.Would something go wrong if I modified the project on a new Mac and submitted the build to the App Store on the new Mac?For example, the data that the user saved in the app is lost.I am so scared that I cannot submit new update build.Can I submit the copied project to the app store?Thank you in advance
2
0
342
Apr ’20