I am getting some issues related to APNG file, APNG file animation working perfect if i put APNG files in resource bundle , But when i have download same APNG file from assets server and saving APNG file into resource directory and then load using MSSticker like this way. after loading it showing only first frame.if anyone wanna try to check APNG file please have a look to this.
let imagePath = Bundle.main.path(forResource: imgName, ofType: ".png")
let pathurl = URL(fileURLWithPath: imagePath!)
do {
try cell.stickerview.sticker = MSSticker(contentsOfFileURL: pathurl, localizedDescription: "anything that you want")
}
catch {
fatalError("Failed to create sticker: \(error)")
}
Here i am saving image & getting saved image url from resource directory:
static func saveImage(image: UIImage , name:String) -> Bool? {
guard let data = UIImagePNGRepresentation(image) else {
return false
}
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do {
try data.write(to: directory.appendingPathComponent(name)!)
return true
} catch {
print(error.localizedDescription)
return false
}
}
static func getSavedImageUrl(named: String) -> URL? {
if let dir = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) {
return URL(fileURLWithPath: dir.absoluteString).appendingPathComponent(named)
}
return nil
}
I have written the extension in custom MSSticker class
extension MSStickerView {
func downloadedFrom(url: URL , name: String) {
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { () -> Void in
// self.sticker = image
_ = GameUtil.saveImage(image: image, name: name)
if let pathurl = GameUtil.getSavedImageUrl(named: name) {
do {
try self.sticker = MSSticker(contentsOfFileURL: pathurl, localizedDescription: "Raid")
}
catch {
fatalError("Failed to create sticker: \(error)")
}
}
self.startAnimating()
}
}.resume()
}
func downloadedFrom(link: String , name: String) {
guard let url = URL(string: link) else { return }
downloadedFrom(url: url ,name: name)
}
I think problem is this UIImagePNGRepresentation. Why convert Data to UIImage and then use UIImagePNGRepresentation.
Try saving data directly.
static func saveData(data: Data , name:String) -> Bool? {
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do {
try data.write(to: directory.appendingPathComponent(name)!)
return true
} catch {
print(error.localizedDescription)
return false
}
}
And ignore image just pass data.
_ = GameUtil.saveImage(data: data, name: name)
Related
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.
This is Doc File Generate in Postman by write method and url "link/services.php".
This is Header File.
#Headers({"Content-Type: application/json"})
#POST("services.php")
Observable<Division> divisionListApi(#Body HashMap<String, String> map);
map.put("method", "My_List");
After Postman Generation I Got This Given Below.
{"err_code":9,
"message":"My List ",
"list":[
{"ForestDivision":"Yam(T)"},
{"ForestDivision":"Rewar(T)"},
{"ForestDivision":"Ro(T)"},
{"ForestDivision":"Bh(T)"},
{"ForestDivision":"Ka(T) "},
{"ForestDivision":"Ambal(T) "},
{"ForestDivision":"Fari(T)"}]
}
I have made request by taking post mehod, is this the right way to create code in
swiftui.
import Foundation
import Combine
struct File: Decodable, Hashable {
var error_code : Int
var message : String
var list : [lisst]
}
struct lisst: Decodable, Hashable {
var ForestDivision: String
}
class fetchResults : ObservableObject{
#Published var fetchedRes : [lisst]?
func getData(completion: #escaping (File) -> ()){
print("Fetch")
let parameters = "{ I dont Know }"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string:
"URl")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { (data, _, _) in
let resultList = try! JSONDecoder().decode(File.self, from: data!)
print(" ")
print("ID: \(resultList.error_code)")
print("VOLUME: \(resultList.message)")
print("READINGS: \(String(describing: resultList.list))")
print(" ")
print("SUCCESS: Got data - \(data! )")
DispatchQueue.main.async {
completion(resultList) // << here !!
}
}
task.resume()
}
}
Also How to Write in Swiftui View.
To Make Properly Works in List View.
import SwiftUI
import UIKit
struct DivisionList: View {
#ObservedObject var res = fetchResults()
var body: some View {
NavigationView {
Text("Nothing Here")
List(res.fetchedRes ?? [], id: \.self) { resp in // Error Here
ForEach(res.list, id: \.self) { course in
VStack {
Text(res.for) // Error Here
}
}
}
.navigationBarTitle("Data")
.onAppear(perform: {
self.getData // Error Here
})
}
}
}
struct DivisionList_Previews: PreviewProvider {
static var previews: some View {
DivisionList()
}
}
Create New Swift File Copy this Post Requests.
import Foundation
import Combine
let postUrl = "Your URl"
struct divisionList: Decodable, Identifiable {
let id: Int
let mesg: String
let list: [FDivision]
private enum CodingKeys: String, CodingKey {
case id = "err_code"
case mesg = "message"
case list = "list"
}
}
struct FDivision: Decodable, Hashable {
let forestDivision: String
private enum CodingKeys: String, CodingKey {
case forestDivision = "ForestDivision"
}
init(data:String) {
forestDivision = data
}
}
class viewModal: ObservableObject {
#Published var items = [FDivision]()
func postData() {
guard let serviceUrl = URL(string: postUrl) else { return }
let parameters: [String: Any] = [
"method": "Your Method Name"
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
request.timeoutInterval = 20
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let dictionary = json as? [String:Any] {
if let arrList = dictionary["list"] as? [[String:Any]]{
for data in arrList{
let model = FDivision(data: data["ForestDivision"] as! String)
self.items.append(model)
}
}
}
print(json)
} catch {
print(error)
}
}
}.resume()
}
}
Create Now New Swiftui File.
import SwiftUI
import UIKit
struct DivisionList: View {
#ObservedObject var vm = viewModal()
var body: some View {
NavigationView {
VStack {
List(vm.items, id: \.self) { item in
Button(action: {}, label: {
Text(item.forestDivision).foregroundColor(.customGreen)
})
}
}.navigationBarTitle("Data")
.onAppear(perform: {
vm.postData()
})
}
}
}
struct DivisionList_Previews: PreviewProvider {
static var previews: some View {
DivisionList()
}
}
I was not able to import or export PDF nor .doc documents to my app. This code below saves selected pdf inside iCloud or phone memory but when I try to view the pdf file it always converts to a document with only text "Hello World".
I guess I need to change allowedContentTypes in .fileImporter and contentType inside .fileExporter but after some research I could not find working example on the web.
#State private var document: MessageDocument = MessageDocument(message: "Hello, World!")
.fileImporter(
isPresented: $isImporting,
allowedContentTypes: [UTType.pdf],
allowsMultipleSelection: false
) { result in
do {
guard let selectedFile: URL = try result.get().first else { return }
//trying to get access to url contents
if (CFURLStartAccessingSecurityScopedResource(selectedFile as CFURL)) {
guard let message = String(data: try Data(contentsOf: selectedFile), encoding: .utf8) else { return }
document.message = message
//done accessing the url
CFURLStopAccessingSecurityScopedResource(selectedFile as CFURL)
}
else {
print("Permission error!")
}
} catch {
// Handle failure.
print(error.localizedDescription)
}
}
.fileExporter(
isPresented: $isExporting,
document: document,
contentType: UTType.data,
defaultFilename: "Message"
) { result in
if case .success = result {
// Handle success.
} else {
// Handle failure.
}
}
}
}
MessageDocument
import SwiftUI
import UniformTypeIdentifiers
struct MessageDocument: FileDocument {
static var readableContentTypes: [UTType] { [.plainText] }
var message: String
init(message: String) {
self.message = message
}
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents,
let string = String(data: data, encoding: .utf8)
else {
throw CocoaError(.fileReadCorruptFile)
}
message = string
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
return FileWrapper(regularFileWithContents: message.data(using: .utf8)!)
}
}
I get this error on uploading image on aws s3 bucket:
2016-11-12 14:03:43.095 Let's Habit[5144:69128] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSConcreteData initWithBytes:length:copy:deallocator:]: absurd length: 18446744073709551615, maximum size: 9223372036854775808 bytes'
I am using following code for the request:
let fileURL :NSURL = NSURL(string:"\(documentsUrl1)MyappDirectory")!
let filePath = fileURL.path!
let newimg :UIImage = (captureImage?.resizeWithPercentage(0.1))!
let imageData = UIImagePNGRepresentation(newimg)
print(imageData!.length)
imageData!.writeToFile(filePath as String, atomically: true)
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.body = fileURL
uploadRequest.key = fileName
uploadRequest.bucket = S3BucketName
self.upload(uploadRequest)
func upload(uploadRequest: AWSS3TransferManagerUploadRequest) {
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
transferManager.upload(uploadRequest).continueWithBlock { (task) -> AnyObject! in
print(task)
if let error = task.error {
if error.domain == AWSS3TransferManagerErrorDomain as String {
if let errorCode = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch (errorCode) {
case .Cancelled, .Paused:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
})
break;
default:
print("upload() failed: [\(error)]")
break;
}
} else {
print("upload() failed: [\(error)]")
}
} else {
print("upload() failed: [\(error)]")
}
}
if let exception = task.exception {
print("upload() failed: [\(exception)]")
}
if task.result != nil {
print(task.result)
let url = task.result
print(url)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("https://s3-us-west-2.amazonaws.com/\(uploadRequest.bucket!)/\(uploadRequest.key!)")
})
}
return nil
}
}
How to resolve this error?
I had the same problem. The solution for me was to append the file name to the file URL which was pointing to a directory
uploadRequest.body = fileURL+fileName
I have the following code snippet to load an image from an url:
let url = NSURL(string: imageUrl)
let data = NSData(contentsOfURL: url!)
let image = UIImage(data: data!)
In case that my variable imageUrl has a valid string value, what is the most secure way to protect this code against possible edge cases?
Following code seems not to be very handy:
if let url = NSURL(string: imageUrl) {
if let data = NSData(contentsOfURL: url) {
if let image = UIImage(data: data) {
// success -> do something with the image...
}
else {
// print error message
}
}
else {
// print error message
}
}
else {
// print error message
}
The best practice is not to use a synchronous method like contentsOfURL to load data from over the network.
The recommended way is NSURLSession which works asynchronously.
This is a simple example with a completion block and an enum with associated types,
it catches all possible errors
enum Result {
case Success(UIImage), Failure(NSString)
}
func loadImage(string : String, completion: (Result) -> ()) {
guard let url = NSURL(string: string) else {
completion(.Failure("Bad URL"))
return
}
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
completion(.Failure(error!.localizedDescription))
} else {
guard let image = UIImage(data: data!) else {
completion(.Failure("Could not load image data"))
return
}
completion(.Success(image))
}
}.resume()
}
Call it with:
loadImage("http://myserver.com/path/to/image.png") { result in
switch result {
case .Success(let image) :
// do something with the image
case .Failure(let error) :
print(error)
}
}