How to delete image from array of strings? - ios

I have a problem with deleting images from my app. I have an array of string, that are images converted to base64 string. So I get back array from API back to my app, and I'm stuck when I want to delete one picture that user has select.
I tried to delete with filter and map method but didn't solve the problem. Here is my "try" "
func deleteImage(image : UIImageView) {
for img in newAdedImages {
newAdedImages = newAdedImages.filter({$0 !== image})
newAdedImages.append(img)
}
}

Bad code
As #vadian already pointed out code you've posted doesn't make sense because you are trying to filter array of strings with instance of UIImageView. Also you are adding string to array which already contains that string that means you will have a lot of duplicates.
Possible solution
You could check how base64 string is used to create UIImage that is used in UIImageView then you can try to reverse process and extract base64 string from UIImage. Then you can filter array of newAddedImages by comparing string values.
Check this answer on SO: https://stackoverflow.com/a/47610733/4949050

try === operator
or add some property to identify your image, also all UIView subclasses have .tag property which can be used as identifier
upd: if you are trying to compare base64 string with UIImageView then seems like u doing something wrong, its better to store UIImageView instead of base64 strings. Imagine your app in abstractions, all the "UI/visual" is view abstraction and the "data" (e.g. base64 strings coming from server) is **data abstraction so u shouldnt mix them up. I dont know the context of your task or so, but there is some pointers I can give:
1) get base64 strings from service/API/etc. (this is data abstraction)
2) use some helper (e.g. some swift class with function) to make UIImage (there goes view abstraction)
3) operate your uiviews as u wish
But this is very simple explanation, I hardly recommend to read more about architecture patterns such as mvvm for example

Related

Base64 Or UIImage.

Based on other question, a based64 image Data is about +37% extra size of the actual String.
Therefore consider this case.
An API Client responses with an Array of Object,
The object contains a lot of properties ..etc, but the one matters is a property i found with a Key of ImageString64 that returns an image of maxWidth & maxHeight by 300x300.
Desired solution:
I want the fastest, yet memory friendly way to decode those images
Notes to consider:
I do know how to encode them, the question is where and why, does it
even matter ?
Options i have: //You can add yours if you have better one
1- inside the Request response callback
2- pass those Objects with their ImageString64 as they are plain String, and then Decode them inside the UIViewController.
More general information about the response:
1- maximum array of object as response is limited between 6 - 9 .
2- each response object, has 17 Keys.
If you need to work with the base64 decoded image, I will transform it neither in the request call back or the view controller.
You should have a type of internal repository, from where your view controllers get the Object instances. The repository contains the raw data, with the base64 string.
If you access one of the object instances from the repository, you should transform the base64 string to an UIImage instance. The view controller should only see the UIImage.
To get good performance for transform and showing the data, you should do this transform before trying to display it, but as mentioned, only if its needed.
If you want to display the data in an UITableView or UICollectionView you should use the prefetching protocols UICollectionViewDataSourcePrefetching (https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data) or UITableViewDataSourcePrefetching (https://developer.apple.com/documentation/uikit/uitableviewdatasourceprefetching).
What's your use case for displaying the images?

Have UIActivityItemProvider return multiple objects or nothing?

I have a Book class and I want to allow my users to share their progress for each book. To do that I present a UIActivityViewController, but I wanted to add different texts for Facebook, Twitter etc., so I had Book conform to the UIActivityItemSource protocol, and then I can return a different value for its methods depending on the activityType. So far so good.
Now I want to also share an image when the user selects Facebook or Twitter, but just text for all other options. The methods in UIActivityItemSource only let me return one object, though. To share both a string and an image it seems I'd have to add them as different activity items, but then I don't know which activityType the user will pick to decide if I should include the image or not.
So how can I share a different number of objects of various classes and values depending on activityType?
Thanks in advance,
Daniel
Edit: Now I'm trying to do this with UIActivityItemProvider… the thing is, sometimes I want to share just some text and sometimes I want to share an image too. So my UIActivityItemProvider would have to return multiple objects conditionally (sometimes it would return an image and sometimes it would not) or I would need to use more than one provider and have the image's provider return nil sometimes, but that doesn't seem to be possible. Now what?
I found a way to work around my problem. It's not great, though, so I won't accept this answer, but I'll leave it here in case it helps someone.
I can't have a UIActivityItemProvider return nil but I can have it return an empty string, so that's what I did – for the activityTypes I want an image I return an image, for the ones I don't I return an empty string. Then I have another provider for the text.
There are a few drawbacks, though. Returning an empty string creates a new line, which isn't a deal breaker, but it's annoying. Also there will always be a string item, even if I return an empty string for my text provider, so options like saving to the camera roll won't ever be available.
I'll do this for now, but if anybody has a better suggestion please let me know.

iOS: Practices for storing a view

My app allows users to customize (add UILabels and UIImages to a UIView. I want the user to be able to retrieve the same view (everything remains at the same location where it was defined). I'm thinking CoreData. I guess I can store everything necessary in a Dictionary<String, AnyObject> including a subview's frame and whatever the user puts inside that view (can be an image or text depending on whether it is a UILabel or UIImage). The storage structure I have in my head is the following:
Dictionary<String, AnyObject>
"frame" : CGRect
"image" : UIImage OR "label" : UILabel
Once I have this ready I can just convert the dictionary into NSData and stuff it into core data.
But is this the correct way of storing views? Any alternative/suggestion on this? Thanks!
=================================UPDATE=================================
The structure I ended up using looks something like this:
NSDictionary
"frame" : CGRect
"content" : UIImage's path on disk / text (for labels)
"type" : "Img" / "Txt"
Since I'm using CoreData, I only needed to make my "view" object extend NSManagedObject and have a dictionary property. This way, the encoding process was no longer needed.
Your approach to creating a dictionary is fair. In a number of ways it would be better to create a custom class (or set of) as these are more specific and provide more compiler checks.
In either case, archiving the store to data is the correct approach (using NSCoding).
Once you have the data you should save it directly to disk rather than using Core Data. Core Data doesn't provide any advantages when storing a single large binary data blob.
Using Core Data properly will only help you if you have many views that you want to store and you don't need to reload them all at the same time. If doing this you wouldn't use a dictionary or data, you would define entities with appropriate attributes.

NSMutableDictionary contents inconsistent with output of allValues

So long story short, there's a discrepancy between the output of a NSMutableDictionary's contents and the result of calling allValues on the same object. Below is some debugger output after inspecting the object which demonstrates my problem: (made generic of course)
(lldb) po self.someDict.allKeys
<__NSArrayI 0xa5a2e00>(
<SomeObject: 0xa5a2dc0>,
<SomeObject: 0xa5a2de0>
)
(lldb) po self.someDict.allValues
<__NSArrayI 0xa895ca0>(
0.5,
0.5
)
(lldb) po self.someDict
{
"<SomeObject: 0xa5a2dc0>" = (null);
"<SomeObject: 0xa5a2de0>" = (null);
}
So as we can see, the actual output of the NSMutableDictionary contains null values for both its entries, but the contents of .allValues contains the proper data. These three outputs were taken at the same time in execution.
I'm not sure why this is happening, but I think it may have something to do with the fact that I'm encoding/decoding the object which this dictionary is a property of using CoreData. I believe I'm doing this properly:
[aCoder encodeObject:self.someDict forKey:#"someDict"];
and to decode
self.someDict = [aDecoder decodeObjectForKey:#"someDict"];
The weird thing is that if I inspect the dictionary before it ever gets encoded, it is still in the state described at the beginning of the post, so this is why I'm doubtful the CoreData actions are screwing with the contents.
As always, please don't hesitate to request additional information.
EDIT: The problem was as answered below. I was using a custom class which didn't cooperate with isEqual, so my solution was to change the storage and structure of my logic, which made using a Dictionary unnecessary.
I have not been able to duplicate the problem using NSString as keys and NSNumber as values. I suspect that your custom class does not properly implement hash and/or isEqual. Specifically, the results from those two methods must be consistent, meaning that if isEqual returns true, then the hash values for the two objects must be identical.
You also need to ensure that your class implements NSCopying properly and that a copy is equal to the original.
As a general rule, don't use custom objects for dictionary keys. Just use strings and be done with it.
As user3386109 points out, custom objects must properly implement the -hash and -isEqual methods in order to be used as dictionary keys, and even then, custom objects don't work correctly for dictionary keys for things like key/value coding.

GWT JSONObject adding an additional incorrect key when converting overlay type to json string

I'm encountering the following problem - I have simple GWT overlay types, and I'm trying to convert one to a JSON string on the client; I'm simply doing:
new JSONObject(this).toString();
The conversion works, but it adds an additional, incorrect key to the json string, such as:
{"key1":"value1", "key2":value2, "$H":1}
where "$H":1 doesn't correspond to anything in my overlay type.
Any idea why this is?
Any help is appreciated on this, thanks.
This issue is define in this link
The $H property comes from the
implementation of
JavaScriptObject#hashCode() (in
com.google.gwt.cire.client.impl.Impl#getHashCode(Object)).
In your case, this is due to
AbstractEditableCell maintaining a map
of value keys to their "view data",
and your use (I guess) of the default
ProvidesKey implementation
(SimpleProvidesKey) which directly
returns the item.
So, when rendering, the EditTextCell
calls getViewData, which looks up the
key in the map (and thus needs the
hashcode of the key, hence the call to
hashCode), and the key is your JSO
(hence the new $H property).
I believe that giving a ProvidesKey
implementation (in you case, returning
the name property for instance) to the
Celltable would solve your issue.

Resources