loading user images works in simulator but not on the iphone xcode 6 Swift - ios

Im trying to load(and upload) images in my app(by picture path).
This is working in my simulator. everything works there. only when im trying to do this on the iphone itself it won't work and i see just the empty UIImageviews.
The paths are loaded the same as in the simulator. And originate from:
PHImageManager.defaultManager().requestImageDataForAsset(asset, options: nil)
{
imageData,dataUTI,orientation,info in
cell.setString(info["PHImageFileSandboxExtensionTokenKey"] as String,name:dataUTI as String)
}
And the PHImageFileSandboxExtentionTokenKey is split into the data and the url when loading the image.
this results in the simulator as :
/Users/Twizzler/Library/Developer/CoreSimulator/Devices/3E671415-8B83-44DA-870F-19BF2BC11F8F/data/Containers/Data/Application/8872109F-3784-40EB-BEB6-4E9FDABE013D/Documents/1613945_10200645161051698_4122753901212984922_n.jpg
and in the iphone as:
/private/var/mobile/Media/DCIM/102APPLE/IMG_2607.JPG
Im loading the image like this:
let image = UIImage(named: "/private/var/mobile/Media/DCIM/102APPLE/IMG_2607.JPG")
cell.imageView.image = image
in this case i put the image url hardcoded (this is in the final app an array of images)
I don't get an error or stack trace. When placeing a breakpoint im seeing the image information in the same way as the simulator
as suggested by the answer im now trying to load them as follows:
let image = UIImage(contentsOfFile: "/private/var/mobile/Media/DCIM/102APPLE/IMG_2607.JPG")
cell.imageView.image = image
This isn't working and i can't upload the files

That’s not how imageNamed works—as the documentation states, that looks for an image with the given name inside your app’s bundle. Try imageWithContentsOfFile.

Well i fixed it! after some puzzling days im now using this way to access upload and
cell.imageView.image = UIImage(data: array[indexPath.row][0] as NSData)
This shows the image. I can save the NSData in the CoreData and reload the image on this way.
To lighten the load on the system im using this:
cellData.checked = 1
var imageData = UIImageJPEGRepresentation(cell.imageView.image, 1)
self.array.append([imageData,cellData.imageData] )
let myObj : ViewControllerImagePicker = self.parentViewController as ViewControllerImagePicker
let textfield: UILabel = myObj.amountLabel! as UILabel
textfield.text = String(self.array.count )
cell.textLabel.alpha = 1
this code is being called when there is clicked on a cell. by setting the cellData.imageData i can recall the cells (when clicking back to the collection view)
I do not know if the way im doing it is correct or works with more that 10 files because of data usage problems. But in my case with a max of 6 selected pictures it works like a charm

The simulator works completely different than a real device when it comes to files, the app bundle and sandboxing.
For starters the simulator will let you write to and add or change files in your app bundle. iOS running on a real device won't let you do this.
You can't hardcode any paths in your app. Even if it works today or on your device in test mode that doesn't mean it will work on a released version. And even if it does it could stop working on any update. Apple several times has changed where things are stored and the path structure in the phone. And where you are allowed to write.
Make bundle calls to get the path locations of standard folders.
Use the assets library to load images from the photo library, or to save them there.
There are tons of resources and tutorials online on how to do this.

Related

Xamarin Forms CircleImage with source from file

I'm using a plugin CircleImage from https://github.com/jamesmontemagno/Xamarin.Plugins/tree/master/ImageCircle
I'm using it in a listview. I noticed it's working fine with image from a url but I can't find a way to show an image from embedded resources or files. Could you explain me how do that?
Thank you in advance!
Is the image in your Resources folder on iOS and Android platforms and in the root on Windows Phone?
You probably want to use the following to set the source of a local image:
Source = ImageSource.FromFile("someimage.png")
Or you might even try:
Source = (FileImageSource)ImageSource.FromFile("someimage.png")
Also be careful with upper and lower case file names. I suggest making everything lower case. The iOS simulator will not care about casing (since Macs do not care), but a real iOS device will care.
For other developers I write and describe my solution for that. I have a MVVM model. In this model there is property
ImageSource image
when I fill the data in the model (r in the example) I verify if taking an embedded image or an image from file system
if (images.Count == 0) {
// from file
r.Image = ImageSource.FromFile ("GenericImageFromResource.png");
} else {
// get the file image from file system
//(required an implementation for each platform)
r.Image = ImageFinder.GetImage (images.First().FileName);
}

Determine memory limit of iOS today extension

I'm developing an iOS today extension, that can read an image from UIPasteboard and save it on disk. This process fails with large images because iOS extensions can't use much memory. To workaround this issue, I'm checking the size of the image first and try to decide, if the widget can save it or should delegate this task to its host app:
let MAXIMUM_IMAGE_SIZE_BYTES = <SomeMagicNumber>
if let clipboardImage = UIPasteboard.generalPasteboard().image {
let imageSize = CGImageGetHeight(clipboardImage.CGImage) * CGImageGetBytesPerRow(clipboardImage.CGImage)
if imageSize > MAXIMUM_IMAGE_SIZE_BYTES {
// Open host app to save image
}
else {
// Save image directly
}
}
I have the following questions:
Is my size calculation correct? I took it from this thread. I cannot instantiate a JPEG or PNG representation and read its size because of the memory limitations mentioned above.
Can I get rid of that magic number for the maximum image size in bytes? If not, are there any official specifications from Apple that I can use? I cannot test my app on every available iOS model and don't want to risk crashes on older devices.
Thanks a lot for your help!
I'm just starting to look at the memory that a notification service extension is using. I found this presentation. Might be helpful for others.
https://cocoaheads.tv/memory-use-in-extensions-by-conrad-kramer/
What was your solution to this issue?

How to get UIImage of AppIcon?

I am using Assets Catalog, and adding app icon of various size to the assets is okay.
But when I tried to get the UIImage programmatically, it returned nil.
UIImage *appIcon = [UIImage imageNamed"AppIcon"];
The app icon is named AppIcon (the default), and the actual files are app-icon-256.png etc.
I also noticed that unlike normal images, app icons are in an "App Icon" set, in the directory AppIcon.appiconset. Normal images are in the directory someimage.imageset.
The problem is that the AppIcon from the asset catalog is not placed in the the catalog after compiling. Instated it it copied into your apps bundle, just like before.
The name conversion used when copying the icon to the app bundle is AppIcon<size>.png, where the size is for example 40x40 or 72x72
You can get your apps icons by specifying the size of the app icon you want:
UIImage *appIcon = [UIImage imageNamed:#"AppIcon40x40"];
The >iOS10 answer is:
Copy & paste this extension.
extension Bundle {
var icon: UIImage? {
if let icons = infoDictionary?["CFBundleIcons"] as? [String: Any],
let primary = icons["CFBundlePrimaryIcon"] as? [String: Any],
let files = primary["CFBundleIconFiles"] as? [String],
let icon = files.last
{
return UIImage(named: icon)
}
return nil
}
}
Then just call this:
Bundle.main.icon
SwiftUI:
Image(uiImage: Bundle.main.icon ?? UIImage())
Update Sep 12 2022: This doesn't work anymore, as of iOS 16.0.0 at least.
The methods of loading the main app icon highlighted in other answers like from Rufat Mirza used to work, and still does for debug builds, but I got an app rejection from Apple saying the app was crashing on launch. Turns out that the builds that contained this code started crashing on iOS 16, but only when installed via App Store/TestFlight (builds using the "Release" Configuration). What's more weird is that builds using the "Release" Configuration compiled via Xcode also wouldn't crash, only when uploaded to App Store and downloaded from TestFlight, so keep this in mind.
The fix was, unfortunately, to create a new Image asset with the same content as the AppIcon asset.
Note that this workaround still works for macOS as of the 12.5.1 and whatever macOS version Apple is using when reviewing their apps as of today, but since I already had to duplicate the asset for iOS, I also used the same asset for macOS to avoid this little hack :)
For those of us, who still need an obj-c version, I made a transcript of the relevant parts of the answer by Rufat Mirza:
NSDictionary *icons = [[NSBundle mainBundle] infoDictionary][#"CFBundleIcons"];
NSDictionary *primary = icons[#"CFBundlePrimaryIcon"];
NSArray *files = primary[#"CFBundleIconFiles"];
return [UIImage imageNamed: files.lastObject];

How can I get raw data of image from UIPasteboard if it's copied by another app (such as photos, safari, etc..)

Is there a way to get raw data of image from UIPasteboard instead of UIImage if it's copied by another app such as photos or mobile safari?
I'm currently facing wired differences between IOS 6.0 and IOS 6.1(7.0 also)
In IOS 6.0, UIPasteboard's item of the copied image by photos or mobile safari contains raw data of the image.
But In IOS 6.1 and above, it contains UIImage instead of raw data.
In IOS 6.0, copied item of UIPasteboard is below
Printing description of array:
<__NSArrayM 0x8a804c0>(
{
"com.compuserve.gif" = <47494638 39614002 ...... 3b3a2000 3b>;
"public.url" = "url of the image....";
}
)
In IOS 6.1 and above, it contains UIImage instead of raw data.
Printing description of array:
<__NSArrayM 0xa25b7b0>(
{
"com.compuserve.gif" = "<UIImage: 0x9429570>";
"public.url" = "url of the image...";
}
)
If that image format is PNG or JPEG, it's not that bad.
(I still have to compress again if it's JEPG though.)
But when I try to paste animated gif image, it becomes more complicated.
I don't know even it's passible to create animated gif image from normal UIImage.
I can download again from original url, but downloading data that I already have seems not good solution I think.
And also, if it's copied from photos app, there's no such url. (there's some mysterious uri named "com.apple.mobileslideshow.asset-object-id-uri" that is undocumented instead of url)
There seems a workaround, because when I try to do exactly same action between photos and email app, It works properly
Any suggestions?
Well now, I figured it out myself.
You can simply get raw (binary)data of the image form general pasteboard by sending
dataForPasteboardType:(NSSting*)PasteboardType message to general pasteboard, if it's copied from Apple's built-in Mobile Safari or Photos App. (#"com.compuserve.gif" for the pasteboard type in my case)
I myself feel a bit foolish for not having checked all the passible methods sooner. :(
My confusion comes from items property of the UIPasteboard.
I thought that items are containing all of data of current pasteboard. So I try to save that array from pasteboard and want to use it later, but I were totally wrong.
As documented in UIPasteboard Class Reference, the items property contains dictionary with key being the representation type and the "value" the object associated with that type.
At this point of time, The "value" refers really "value" of the representation, not the data of that type. This meaning of the "value" is the same as the value of thesetValue: forPasteboardType: method.
On the other words, you cannot retrieve raw(binary) data of the image from items property, even if you set the image to the pasteboard by sending setData: forPasteboardType: message.(I tested it on IOS 7)
In addition, raw data of the image from items property in IOS 6.0 seems a bug of that OS version. (This may not true, it's just my opinion)
You can get NSData from UIPasteboard if you specify right PasteboardType:
NSData* pasteData = [[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString*)kUTTypeJPEG];
Do not forget to import
<MobileCoreServices/MobileCoreServices.h>
The UIPasteBoard will contain whatever is placed in it. It's up to the app that is copying to the paste board to put the contents in the proper format. The app can place items as raw binary data or as objects such as UIImage in the paste board.
If you're getting something different between iOS versions, you're probably using different versions of the app or it's simply copying things differently.
You're right that you can't represent an animated GIF in a UIImage because a UIImage only contains a single image. Perhaps the app is just copying the first frame's bitmap data in that case?
You can convert a UIImage to raw JPEG data using UIImageJPEGRepresentation.

iOS - UIImage imageNamed: returns null on device

[UIImage imageNamed:filename]
This method returns null only on the device.
I know it's known problem and it's usually due to the fact that simulator is case insensitive.
I have tried solutions proposed here: UIImage imageNamed returns nil
But nothing worked out for me.
The case is simple: I have 4 files named:Bar#2x~ipad.png, Bar#2x~iphone.png, Bar~ipad.png, Bar~iphone.png.
All of them are in project with target checkbox checked.
NSLog(#"%#",[UIImage imageNamed:#"Bar"]);
That line of code gives me null for device and I really have no idea what I'm doing wrong right now.
I did have such a problem recently too.
After playing with filenames and paths sometimes it helps when you clean and rebuild your project.
I found myself in the same situation recently.
The solution in my case was adding the extension to the file name.
[UIImage imageNamed:#"Bar.png"]
Completely clean your build and redo it:
delete the app from the device
option-clean the whole build directory in Xcode (⌘-Shift-K)
quit xcode
delete ~/Library/Developer/Xcode/DerivedData
restart xcode, build and run
This just happened to me, and to discover was very tough: I had one image which where nil just on device
logoWhite.png
my code:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"LogoWhite"] forBarMetrics:UIBarMetricsDefault];
After a while of debugging, I noticed that the name of the image is beginning with capital case letter. Obviously this doesn't matter on OSX with a ignore case file system. iOs file system isn't, so the image worked on the simulator but not on the device.
I bet that all the solutions about cleaning derived data and rebuild did randomly end with renaming the image, and this would do the trick as well. Just posting here for future reference :)
I encountered this issue and just fixed it. I listed the solution below as a reference.
I have several images, and use [UIImage imageNamed:filePath] to show them. All of images displayed well except 1 on simulator/device, but all of them can be seen on OS X. For that image, [UIImage imageNamed] always return null.
After few minutes' investigation, I found that the image cause problem is far big in file size: 4.1M. Others are all around 800kb. They have nearly same size in dimension.
Then I try to open it in image editor, then re-save it. After this, the size dropped to 800k. problem solved.
The reasons I guess,
[UIImage imageNamed:filePath] has a max file size limit? (low possibility, but need to check official document)
the image itself has some error. But OS X has better tolerance than iOS. so iOS cannot read and return null. This issue is like OS X can play more types of video files than iOS since it support more codecs.
so if you encounter this issue in the future, take a few seconds look at the file size. Hope help.
This is an odd problem, which I hadn't seen until this week.
Below are my findings, and a workaround to your problem.
In my iPhone app, I download an image and store it locally, and this had always worked fine.
But now when I run the same code, it was suddenly failing to create a UIImage out of it using the imageNamed function, and now it was returning nil.
Three notes though:
This exact code did work before, using the same source code and .png image files. I'm not sure if my copy of XCode 6.x or iOS 8.x quietly updated itself in the meantime.
The code continues to work okay (with the same image file) on the iPhone simulator. It just doesn't work on a real device.
Take a look at the code below. When UIImage:imageNamed failed, I ran some code to check if the file actually existed.. and it did. Then I loaded the binary data from the file using NSData:contentsAtPath (which also proves that the file exists and was in the right folder), then created a UIImage out of that, and it worked fine.
Huh ?!
UIImage* img = [UIImage imageNamed:backgroundImageFilename];
if (img != nil)
{
// The image loaded fine (this always worked before). Job done.
// We'll set our UIImageView "imgBackgroundView" to contain this image.
self.imgBackgroundView.image = img;
}
else
{
// We were unable to load the image file for some reason.
// Let's investigate why.
// First, I checked whether the image was actually on the device, and this returned TRUE...
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:backgroundImageFilename];
if (fileExists)
NSLog(#"Image file does exist.");
else
NSLog(#"Image file does not exist.");
// Next, I attempted to just load the bytes in the file, and amazingly, this also worked fine...
NSData *data = [[NSFileManager defaultManager] contentsAtPath:backgroundImageFilename];
if (data != nil)
{
// ..and then I COULD actually create a UIImage out of it.
img = [UIImage imageWithData:data];
if (img != nil)
{
// We have managed to load the .png file, and can now
// set our UIImageView "imgBackgroundView" to contain this image.
self.imgBackgroundView.image = img;
}
}
}
As I said, this code does provide a workaround for this problem, but it's very odd that it's suddenly started happening.
And, I should say, I did try the other suggestions in this thread, cleaning the project, removing the DerivedData, completely removing the app from the device, and so on, but they didn't make any difference.
I would be interested in knowing if anyone else hits this issue, and finds that my code sample works for them.
Update
I'm an idiot.
I'm not sure if the UIImage:imageNamed function has changed or something (and if so, why it continues to work okay on the iPhone 8.1 Simulator), but I found the following one line does work okay:
UIImage* img = [[UIImage alloc] initWithContentsOfFile:backgroundImageFilename];
So it seems as though you should use this function for loading images which aren't a part of your app's bundle.
I also have same issue then : XCode - Build Phases - Copy Bundle Resources -{see image is available or not}- add{image} - clean - delete app - Run .
I would like to add one more important point to all the above solutions
Make sure you add your image resource to right target
By mistake if Developer mess-up link with resource and target then conditions arise.
if you have multiple target then double check the resource are set to correct target.
Attached screenshot example in case of resource link between multiple targets.

Resources