change collection optional value in swift? - swift

rowDescriptor is a AnyObject? type, I get convert self.rowDescriptor?.value to images. I want to add image to the self.rowDescriptor?.value. I failed to do it as below. images has one value. but self.rowDescriptor?.value still empty. I can't find any document about it. what's the reason about it.
var images :[UIImage] = self.rowDescriptor?.value as! [UIImage]
if let image = editedImage {
images.append(image)
} else {
images.append(originalImage!)
}

The array type in Swift is a struct. Structs in swift are value types not reference types. To clarify:
images contains a copy of self.rowDescriptor?.value
images.append( changes the copy images, not the original value in your rowDescriptor.value
You want to change self.rowDescriptor?.value so just set that to your newly changed images array.
self.rowDescriptor?.value = images
td;dr
To fix, add self.rowDescriptor?.value = images.

Related

How do I print images from this model?

I have this model.
In Mac, when an image is input, it detects objects and represents what it is.
https://i.stack.imgur.com/qdFBr.png
However, this model has four outputs.
I think the first output is the result.
So I converted the results into an image in Python as follows and saved the model as mlmodel.
import coremltools.proto.FeatureTypes_pb2 as ft
output = spec.description.output[0]
output.type.imageType.colorSpace = ft.ImageFeatureType.GRAYSCALE
output.type.imageType.height = 416
output.type.imageType.width = 416
In Swift, the converted results are stored in this form.
lazy var var_944: CVPixelBuffer = {
[unowned self] in return self.provider.featureValue(for: "var_944")!.imageBufferValue
}()!
After putting an image in the input, convert the output CVPixelBuffer to UIImage, and put UIImage in ImageView, no image appears.
Does anyone know the solution?
(Please understand that I used Papago because I am not good at English.)

Swift MetalKit unknknown return type MTKMesh.newMeshes

Up until now I have been following a tutorial (released around the time of Metal 1), to learn Metal. I haven't encountered any errors I couldn't figure out until this point. I am trying to execute this code
var meshes: [AnyObject]?
//code
let device = MTLDevice() //device is fine
let asset = MDLAsset() //asset works fine
do{
meshes = try MTKMesh.newMeshes(asset: asset, device: device)
} catch //...
The error i'm getting is Cannot assign value of type '(modellOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh])' to type '[AnyObject]?'
What is type of MTKMesh.newMeshes, and how can I store it in a variable? I tried casting it as! [AnyObject], but then xcode tells me that this cast would fail every time.
The return type of that method is ([MDLMesh], [MTKMesh]), a tuple comprised of an array of MTLMeshes and an array of MTKMeshes. The reason for this is that you might want the original collection of MDLMesh objects contained in the asset, in addition to the MTKMesh objects that are created for you.
So, you can declare meshes like this:
var meshes: ([MDLMesh], [MTKMesh])
Or, if you don't care about the original MDLMeshes, you can "destructure" the tuple to get just the portion you care about into a variable of type [MTKMesh]:
var meshes: [MTKMesh]
(_, meshes) = try MTKMesh.newMeshes(asset: asset, device: device)
As the function signature and the compiler error clearly show, the return type is (modelIOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh]), so you should declare meshas accordingly:
var meshes: (modelIOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh])?
The type is a named tuple containing two Arrays, holding MDLMesh and MTKMesh instances respectively.

image from xcassets iOS11

I have a set of images inside an .xcassets folder.
Using iOS 11 and Xcode 9 I access them with
func searchCodes() -> NSArray {
let file = Bundle.main.url(forResource: "PickerStations", withExtension: "plist")
return NSArray(contentsOf: file!)!
}
lineCode = searchCodes().object(at: 1) as? NSDictionary
//lineFirstInitial is either C,H,J,N,P,D,M,V,B or W
let lineNameFromInitial = lineCode?.allKeys(for: lineFirstInitial).first as! String
//lineNameFromInitial is 100% correct value and loaded from an array of Strings.
//Looped through and each value added to the code below.
if let lineLabelImage = UIImage(named: lineNameFromInitial) {
lineLabelImageView.image = lineLabelImage
}
Some Images enter the block and yet others do not as they return nil. However the images are 100% in the .xcassets and the file name is 100% correct. I have tried hardcoding the images name instead of passing the variable lineNameFromInitial but the images are still nil for some despite actually existing.
The images are found using the keys in a plist
Any suggestions?
Two reasons that might be the reason for the images being nil:
1. The images have not been added to your app's target.
2. The images have a name with special characters:
Xcode does not like assets that have special characters like ÄÖÜ etc. in their name. Have a look at the problematic images' names and change those characters to plain old english characters.

Function returning specified values but structure doesn't append its values

https://github.com/mateo951/ISBN-Vista-Jera-rquica- Github Link
The structure I have is supposed to be appending values after an internet search. The internet search is called within a function and returns two strings and an image. When I try to append the returned values in the structure, the image is saved but strings are nil.
var datosLibros = [bookData]()
#IBAction func Search(sender: UITextField) {
let (title1, author1, cover1) = (internetSearch(sender.text!))
let libro = bookData(title: title1, author: author1,image:cover1)
datosLibros.append(libro)
print(datosLibros)
}
The saved structured that is printed to the console is the following:
bookData(title: "", author: "", image: <UIImage: 0x7f851a57fbf0>, {0, 0})
Structure:
struct bookData {
var title: String
var author: String
var image: UIImage
init(title: String, author: String, image: UIImage) {
self.title = title
self.author = author
self.image = image
}
}
Thanks in advanced for any advice of help provided. I'm new to swift so there are a lot of stuff uncovered.
The problem is not with the code you posted but with internetSearch.
But before I explain what is going on there, just a quick note about Swift structs. Structs come with one free initializer that takes as its parameters one value for each stored property defined on the struct. Argument labels correspond to the variable labels.
So for your struct bookData (which really should be BookData since types should be capitalized), you do not need to include that initializer you wrote because it will be automatically provided for you as long as you do not create any additional BookData initializers.
Now for the reason your results are not what you expect. Your Strings are not coming back as nil. Instead, they are coming back as empty Strings, or "". In Swift, "" is very different from nil, which means a complete absence of a value. So your Strings are indeed there, they are just empty.
Okay, our Strings are coming back empty. How about our image? No, our image is not coming back either. You thought it was because you saw a UIImage reference printed in the console, but if you look closer you will notice it is a bogus image. Notice "{0, 0}" after the memory address for the instance. As far as I'm aware, this means the image has a size of 0 x 0. How many useful images do you know that have a size of 0 x 0?
So now we have discovered that our Strings are coming back empty and effectively so is our image. What is going on here?
Well, in your implementation of internetSearch I found on GitHub, this is the first thing you do:
var bookTitle = String()
var bookAuthor = String()
var bookCover = UIImage()
Naturally, you do this so that you have some variables of the correct types ready to plop in some actual results if you find them. Just for fun, let's see what the result of the code above would be if there were no results.
Well, the initializer for String that accepts no parameters results in an empty String being created.
Okay, how about our image. While the documentation for UIImage does not even mention an initializer that takes no parameters, it does inherit one from NSObject and it turns out that it will just create an empty image object.
So we now have discovered that what internetSearch is returning is actually the same as what it would be if there were no results. Assuming you are searching for something that you know exists, there must be a problem with the search logic, right? Not necessarily. I noticed that your implementation of the rest of internetSearch relies on an NSURLSession that you use like so:
var bookTitle = String()
var bookAuthor = String()
var bookCover = UIImage()
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in
// Lots of code that eventually sets the three variables above to a found result
}
task.resume()
return (bookTitle, bookAuthor, bookCover)
That seems fine and dandy, except for the fact that NSURLSession performs its tasks asynchronously! Yes, in parts you even dispatch back to the main queue to perform some tasks, but the closure as a whole is asynchronous. This means that as soon as you call task.resume(), NSURLSession executes that task on its own thread/queue/network and as soon as that task is set up it returns way before it completes. So task.resume() returns almost immediately, before any of your search code in the task actually runs, and especially before it completes.
The runtime then goes to the next line and returns those three variables, just like you told it to. This, of course, is the problem because your internetSearch function is returning those initial empty variables before task has a chance to run asynchronously and set them to helpful values.
Suggesting a fully-functional solution is probably beyond the scope of this already-long answer, but it will require a big change in your implementation detail and you should search around for using data returned by NSURLSession.
One possible solution, without me posting any code, is to have your internetSearch function not return anything, but on completion of the task call a function that would then append the result to an array and print it out, like you show. Please research this concept.
Also, I recommend changing your implementation of internetSearch further by declaring your initial values not as:
var bookTitle = String()
var bookAuthor = String()
var bookCover = UIImage()
…but as:
var bookTitle: String?
var bookAuthor: String?
var bookCover: UIImage?
This way, if you find a result than you can represent it wrapped in an Optional and if not you can represent that as nil, which will automatically be the default value of the variables in the code directly above.

Best way to display swiftyjson parsed data?

After already having parsed my data through swiftyjson I am looking to display the parsed information in a uitableview. Let's say I have a list of names that I parsed out of the json file. I would like those names to display each in their own respective cells to allow the user to view them all.
I would also assume that if they selected the selected cells which are being displayed strings now after being parsed that I can actually have those stored into a core data object storing them as returnable strings? The thing is I used the .append function onto an array that I created we'll call names = [String]() to actually allow the values to actually come in order for the cells.
But when doing this I noticed a huge spike in cpu usage doing this as it keeps appending them in order lets say first name is matt second name is john and so forth then it creates a new situation of the array every time. so the first time it reads just matt then the next println would print out matt, john then the next one prints out matt, john, tom and so forth until the list of json names is completed.
If I have 500 names or more it takes the cpu awhile to process all those names into the array. I know there has to be another way but all references I see all use the .append method. So my code would be names.append(Name). Name is a parsed string from swiftyjson. From there I am actually able to populate the tableview which is fine it displays correctly in the end but it takes the device awhile to populate as it first needs to process adding all 500 names each time the parse is called. I am hoping to allow the 500 names be rechecked every time in case new ones have been added. This all stores currently as a local json file already.
The code I am using is below I can figure out the UItableview part but it's more a question of whether appending an array is the best and most efficient way of displaying the parsed data from swiftyjson.
let path = NSBundle.mainBundle().pathForResource("List", ofType: "json")
let jsonData = NSData(contentsOfFile: path!, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil)
let json = JSON(data: jsonData!)
for (key, subJson) in json["array"] {
if let Name = subJson["Name"].string {
NameList.append(Name)
println(NameList)
}
}
maybe the Swift map function is more effective
…
let json = JSON(data: jsonData!)
var nameList = [String]()
if let subJson = json["array"] as [Dictionary<String,NSObject>]? {
nameList = subJson.map { $0["name"] as! String }
}