The EKCalendarItem has the property "Location", but it is a NSString.
New iOS8 functionality shows a nice map for an event, so there must be a CLLocationCoordinate2D attached to the EKCalendarItem, correct?
Where can I find this CLLocationCoordinate2D?
this should get what you need:
for (EKEvent *calEvent in self.allMyEvents) {
EKStructuredLocation *location = (EKStructuredLocation *)[calEvent valueForKey:#"structuredLocation"];
if (location) {
}
}
EKCalendarItem does not contain any CLLocationCoordinate2D property it has location which is NSString as you mentioned in your question.
You can use location property to get co-ordinates. You can get the coordinates from a string using CoreLocation framework's CLGeocoder .
You can use this code.
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:locationString completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count]) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D coordinate = location.coordinate;
NSLog(#"coordinate = (%f, %f)", coordinate.latitude, coordinate.longitude);
}
}];
Here locationString is the location string retrieved from EKCalendarItem 's location property. The default iCal app must be doing something similar, Hope this helps you.
Related
Is it possible to read the name of an UIImageView's UIImage
that's presently stored in the UIImageView?
I was hoping you could do something kind of like this, but haven't figured it out.
NSString *currentImageName = [MyIImageView getFileName];
you can use setAccessibilityIdentifier method for any subclass of UIView
UIImageView *image ;
[image setAccessibilityIdentifier:#"file name"] ;
NSString *file_name = [image accessibilityIdentifier] ;
Nope. You can't do that.
The reason is that a UIImageView instance does not store an image file. It stores a displays a UIImage instance. When you make an image from a file, you do something like this:
UIImage *picture = [UIImage imageNamed:#"myFile.png"];
Once this is done, there is no longer any reference to the filename. The UIImage instance contains the data, regardless of where it got it. Thus, the UIImageView couldn't possibly know the filename.
Also, even if you could, you would never get filename info from a view. That breaks MVC.
No no no… in general these things are possible. It'll just make you feel like a dirty person. If you absolutely must, do this:
Create a category with your own implementation of +imageNamed:(NSString*)imageName that calls through to the existing implementation and uses the technique identified here (How do I use objc_setAssociatedObject/objc_getAssociatedObject inside an object?) to permanently associate imageName with the UIImage object that is returned.
Use Method Swizzling to swap the provided implementation of imageNamed: for your implementation in the method lookup table of the Objective-C runtime.
Access the name you associated with the UIImage instance (using objc_getAssociatedObject) anytime you want it.
I can verify that this works, with the caveat that you can't get the names of UIImage's loaded in NIBs. It appears that images loaded from NIBs are not created through any standard function calls, so it's really a mystery to me.
I'm leaving the implementation up to you. Copy-pasting code that screws with the Objective-C runtime is a very bad idea, so think carefully about your project's needs and implement this only if you must.
There is no native way to do this; however, you could easily create this behavior yourself.
You can subclass UIImageView and add a new instance variable:
NSString* imageFileName;
Then you could override setImage, first setting imageFileName to the filename of the image you're setting, and then calling [super setImage:imageFileName]. Something like this:
-(void) setImage:(NSString*)fileName
{
imageFileName = fileName;
[super setImage:fileName];
}
Just because it can't be done natively doesn't mean it isn't possible :)
if ([imageForCheckMark.image isEqual:[UIImage imageNamed:#"crossCheckMark.png"]]||[imageForCheckMark.image isEqual:[UIImage imageNamed:#"checkMark.png"]])
{
}
Nope. No way to do that natively.
You're going to have to subclass UIImageView, and add an imageFileName property (which you set when you set the image).
Neither UIImageView not UIImage holds on to the filename of the image loaded.
You can either
1: (as suggested by Kenny Winker above) subclass UIImageView to have a fileName property or
2: name the image files with numbers (image1.jpg, image2.jpg etc) and tag those images with the corresponding number (tag=1 for image1.jpg, tag=2 for image2.jpg etc) or
3: Have a class level variable (eg. NSString *currentFileName) which updates whenever you update the UIImageView's image
Or you can use the restoration identifier, like this:
let myImageView = UIImageView()
myImageView.image = UIImage(named: "anyImage")
myImageView.restorationIdentifier = "anyImage" // Same name as image's name!
// Later, in UI Tests:
print(myImageView.restorationIdentifier!) // Prints "anyImage"
Basically in this solution you're using the restoration identifier to hold the image's name, so you can use it later anywhere. If you update the image, you must also update the restoration identifier, like this:
myImageView.restorationIdentifier = "newImageName"
I hope that helps you, good luck!
This code will help you out:-
- (NSString *)getFileName:(UIImageView *)imgView{
NSString *imgName = [imgView image].accessibilityIdentifier;
NSLog(#"%#",imgName);
return imgName;
}
Use this as:-
NSString *currentImageName = [self getFileName:MyIImageView];
In short:
uiImageView.image?.imageAsset?.value(forKey: "assetName")
UIImage has an imageAsset property (since iOS 8.0) that references the UIImageAsset it was created from (if any).
UIImageAsset has an assetName property that has the information you want. Unfortunately it is not public, hence the need to use value(forKey: "assetName"). Use at your own risk, as it's officially out of bounds for the App Store.
Yes you can compare with the help of data like below code
UITableViewCell *cell = (UITableViewCell*)[self.view viewWithTag:indexPath.row + 100];
UIImage *secondImage = [UIImage imageNamed:#"boxhover.png"];
NSData *imgData1 = UIImagePNGRepresentation(cell.imageView.image);
NSData *imgData2 = UIImagePNGRepresentation(secondImage);
BOOL isCompare = [imgData1 isEqual:imgData2];
if(isCompare)
{
//contain same image
cell.imageView.image = [UIImage imageNamed:#"box.png"];
}
else
{
//does not contain same image
cell.imageView.image = secondImage;
}
You can use objective c Runtime feature for associating imagename with the UImageView.
First import #import <objc/runtime.h> in your class
then implement your code as below :
NSString *filename = #"exampleImage";
UIImage *image = [UIImage imagedName:filename];
objc_setAssociatedObject(image, "imageFilename", filename, OBJC_ASSOCIATION_COPY);
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
//You can then get the image later:
NSString *filename = objc_getAssociatedObject(imageView, "imageFilename");
Hope it helps you.
Get image name Swift 4.2
There is a way if you want to compare button image names that you have in assets.
#IBOutlet weak var extraShotCheckbox: UIButton!
#IBAction func extraShotCheckBoxAction(_ sender: Any) {
extraShotCheckbox.setImage(changeCheckBoxImage(button: extraShotCheckbox), for: .normal)
}
func changeCheckBoxImage(button: UIButton) -> UIImage {
if let imageView = button.imageView, let image = imageView.image {
if image == UIImage(named: "checkboxGrayOn") {
return UIImage(named: "checkbox")!
} else {
return UIImage(named: "checkboxGrayOn")!
}
}
return UIImage()
}
Swift 3
First set the accessibilityIdentifier as imageName
myImageView.image?.accessibilityIdentifier = "add-image"
Then Use the following code.
extension UIImageView {
func getFileName() -> String? {
// First set accessibilityIdentifier of image before calling.
let imgName = self.image?.accessibilityIdentifier
return imgName
}
}
Finally, The calling way of method to identify
myImageView.getFileName()
I have deal with this problem, I have been solved it by MVC design pattern, I created Card class:
#interface Card : NSObject
#property (strong,nonatomic) UIImage* img;
#property (strong,nonatomic) NSString* url;
#end
//then in the UIViewController in the DidLoad Method to Do :
// init Cards
Card* card10= [[Card alloc]init];
card10.url=#"image.jpg";
card10.img = [UIImage imageNamed:[card10 url]];
// for Example
UIImageView * myImageView = [[UIImageView alloc]initWithImage:card10.img];
[self.view addSubview:myImageView];
//may you want to check the image name , so you can do this:
//for example
NSString * str = #"image.jpg";
if([str isEqualToString: [card10 url]]){
// your code here
}
use below
UIImageView *imageView = ((UIImageView *)(barButtonItem.customView.subviews.lastObject));
file_name = imageView.accessibilityLabel;
The code is work in swift3 - write code inside didFinishPickingMediaWithInfo delegate method:
if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? NSURL {
ALAssetsLibrary().asset(for: referenceUrl as URL!, resultBlock: { asset in
let fileName = asset?.defaultRepresentation().filename()
print(fileName!)
//do whatever with your file name
}, failureBlock: nil)
}
I am learning to use SwiftUI with Core Data.
I am trying to fill a Line Chart with saved weight data like below:
LineView(data: [0, 32, 445, 56, 99])
I’ve gotten as far as this but im getting an error on the "var locations = ..." line saying "Type of expression is ambiguous without more context"
var fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserWeight")
var locations = mocW.executeFetchRequest(fetchRequest, error: nil) as [UserWeight]
for weight in weights {
print(weights.userWeight)
}
Any help on this and how i would populate the line chart with this data would be greatly appreciated!
For SwiftUI, I suspect that you are attempting to achieve the following...
struct YourView: View {
#FetchRequest(entity: UserWeight.entity(),
sortDescriptors: []
) var weights: FetchedResults<UserWeight>
var body: some View {
ForEach(weights) { weight in
Text(weight.userWeight)
}
}
}
Core Data entities confirm to the Identifiable protocol, so you'e able to drop the id: parameter in the ForEach structure...
ForEach(weights) { weight in
Otherwise you'd need to use...
ForEach(weights, id: \.self) { weight in
Note: As an aside, it would help us if you could provide more detail in your questions in the future. The more information you provide, the easier it is for the community to understand your issue and provide a suitable response. Remember that your question and our answers may not only help you, but also help others in the future as they visit the site looking for answers to their own problems.
How do I ask a good question?
if let appDelegate =
UIApplication.shared.delegate as? AppDelegate {
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<Memory>(entityName: "Memory")
let sortDescriptor = NSSortDescriptor(key: "rating", ascending: false)
var predicate = NSPredicate(format: "mediaType == %#", "image")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
do {
result = try managedObjectContext.fetch(fetchRequest)
} catch {
}
}
"result" is an array of, in my case, Memory objects which are instances of NSManagedObject. To access properties and populate views I do this:
for memory in result {
let value = memory.entityPropertyName
}
I think this should be enough to get your started, let me know if you have more questions.
If UserWeight is a subclass of NSManagedObject, you should declare your fetch request as
var fetchRequest = NSFetchRequest<UserWeight>(entityName: "UserWeight")
Or else as
let fetchRequest: NSFetchRequest<UserWeight> = UserWeight.fetchRequest()
Then you can use the fetch like this, and the type of locations will be Array<UserWeight>.
let locations = try context.fetch(fetchRequest)
I'm not sure where executeFetchRequest(fetchRequest, error: nil) comes from-- it's not a function defined by NSManagedObjectContext in Swift. It resembles the Objective-C version of the function, but in Swift it's different.
I want to be able to save an array, cardImages, that contains UIImages via SwiftyUserDefaults.
Desired Behavior
Here is the exact desired behavior:
Save an array of UIImages to NSUserDefaults via the SwiftyUserDefault library
Retrieve the images later
Code This is stripped down to very little code
var newPhotoKey = DefaultsKey<NSArray>("image")//Setting up the SwiftyUserDefaults Persisted Array
cardImages = [(UIImage(named: "MyImageName.jpg")!)] //This array contains the default value, and will fill up with more
Defaults[theKeyForStoringThisArray] = cardImages //This is the persisted array in which the array full of images should be stored. WHERE THE ERROR HAPPENS
var arrayToRetreiveWith = Defaults[theKeyForStoringThisArray] as! [UIImage] //To Retreive
Error
I get the following error:
Attempt to set a non-property-list object (
", {300, 300}"
) as an NSUserDefaults/CFPreferences value for key image
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object (
", {300, 300}"
) for key image'
Thanks!
The error message is clear actually. UIImage is not a propertylist so you need to change it to a row data first. I'll put example below but FYI saving big data like images using NSUserDefaults is really not recommended. I'd use NSFileManager and put it in the user documents directory. anyway
var newPhotoKey = DefaultsKey<NSArray>("image")
cardImages = [(UIImage(named: "MyImageName.jpg")!)]
var cardImagesRowdataArray: NSData = []
for image in cardImages {
let imageData = UIImageJPEGRepresentation(image, 1.0)
cardImagesRowdataArray.append(imageData)
}
Defaults[theKeyForStoringThisArray] = cardImagesRowdataArray
var arrayToRetreiveWith = Defaults[theKeyForStoringThisArray] as! [NSData]
// here you can use UIImage(data: data) to get it back
If you don't insist on using SwiftyUserDefaults, you can save it in the user documents directory, here is how to do it
func saveImage(image: UIImage){
if let imageData = UIImageJPEGRepresentation(image, 1.0) {
let manager = NSFileManager()
if let docUrl = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first{
let uniqueName = NSDate.timeIntervalSinceReferenceDate()
let url = docUrl.URLByAppendingPathComponent("\(uniqueName).jpg")
imageData.writeToURL(url, atomically: true)
}
}
}
The value of a user default must be a property list. A property list is
a string (String or NSString),
an NSData,
a date (NSDate),
a number (NSNumber),
a boolean (also NSNumber),
an array of property lists,
or a dictionary whose keys are strings and whose values are property lists.
A UIImage is none of those, so a UIImage is not a property list and cannot be part of a property list.
You need to convert your image to an NSData to store it in a user default. Since a UIImage contains some properties (like scale and imageOrientation) in addition to raw pixel data, the easiest way to convert a UIImage to an NSData with no loss is by creating an archive:
let cardImage: UIImage? = someImage()
let cardImageArchive: NSData = NSKeyedArchiver.archivedDataWithRootObject(cardImage!)
Now you can store cardImageArchive in a larger property list that you can store as a user default.
Later, when you need to recreate the image from the data, do this:
let cardImageArchive: NSData = dataFromUserDefaults()
let cardImage: UIImage = NSKeyedUnarchiver.unarchiveObjectWithData(cardImageArchive) as! UIImage
Well I have been making a test app to continue my swift learning, today I came across a problem.
Basically I have a tableview and a detailview. For my tableview file I have some data that I am currently passing to the detailview, like the name that goes on the navigation bar, one image and some text, this data is stored in arrays on my tableview file, I use "prepareforsegue" to pass this information:
var names = ["name1","name2","name3"]
detailViewController.detailName = names[indexPath.row]
Then in my detailViewController I have variables set for that:
var detailName: String?
Then I use this for stuff, example: naming my navigation bar or setting an image in detailView:
navigationItem.title = detailName!
Now, what I dont get how to do is pass a whole array of information to a variable in my detailViewController. What I want to do is pass an array of images to use it on my detailView. I want to be able to iterate through the array of images with a button, I know how to set that up but I just need to know how to pass the array, right now I am just passing one of the values(one name, one image etc...)
Thanks for the help in advance.
It's not so different from what you have done.
Just add field for images in detailViewController, and then pass images using it. Images could be represented in [UIImage]. However, [String] can be also used for local filenames, and [NSURL] can be used for remote image urls.
code:
In DetailViewController:
var images: [UIImage]? // or var images: [UIImage] = []
In prepareForSegue:
detailViewController.images = YourImages
You seem to be asking for one of two things:
A UIImage array, which you can declare using var imageArray : [UIImage] = [] and then append whatever images you want to pass.
Alternatively, you can pass in a [AnyObject] array and cast its elements to a UIImage or String by doing
var objectArray : [AnyObject] = []
objectArray.append("test")
objectArray.append(UIImage(named: "test.png")!)
if let s = objectArray[0] as? String {
// Do something with the string
}
if let i = objectArray[1] as? UIImage {
// Do something with the image
}
if let s = objectArray[1] as? String {
// The above cast fails, this code block won't be executed
} else {
// ... but this one will
}
in the table view controller file:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get reference to the destination view controller
var detailVC = segue.destinationViewController as! DetailViewController
var detailImages: Array<UIImage> = []
detailImages.append(UIImage(named: "pup.png")!)
detailImages.append(UIImage(named: "cutepuppy.png")!)
detailVC.detailImages = detailImages;
}
and in the detail file:
var detailImages: Array<UIImage>?
I am making a calorie counter and I have created an UIAlertView which gives me list of food items. I have made a NSMutableDictionary containing the food and the calories:
#implementation FoodDatabase
-(id)init
{
self = [super init];
if(self)
{
food= [[NSMutableDictionary alloc] init];
[food setObject:#"111" forKey:#"Rice"];
}
return self;
}
-(NSString *) foodList: (NSString *) foodItem
{
for(NSString *key in [food allKeys])
{
if([foodItem isEqual: key])
{
NSLog(#"%#",foodItem);
return [food objectForKey:foodItem];
}
}
}
#end
In another class, I have created an UIAlertView which gives a list of food items. This is the code snippet for the item Rice:
NSString *buttonTitle = [alertView buttonTitleAtIndex:buttonIndex];
if([buttonTitle isEqualToString:#"Rice"])
{
NSString *xyz = [foodData foodList: #"Rice"];
food_calorie = ([xyz floatValue]);
UIAlertView *rice_alert=[[UIAlertView alloc] initWithTitle:#"Enter quantity of rice consumed" message:#"100 gms = 111 calories" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[rice_alert addTextFieldWithValue:#"" label:#"Enter quantity in gms"];
RiceText = [rice_alert textFieldAtIndex:0];
RiceText.keyboardType = UIKeyboardTypeNumberPad;
RiceText.clearsOnBeginEditing = YES;
RiceText.clearButtonMode = UITextFieldViewModeWhileEditing;
RiceText.keyboardAppearance = UIKeyboardAppearanceAlert;
rice_alert.tag = RiceAlertView;
[rice_alert show];
[rice_alert release];
}
I calculate the total calories by using the value entered by the user in the _RiceText_ and the value of the _object_ returned for a specific key (in this case rice). But it seems not to be returning the value of the _object_ as the NSLog shows _(null)_ for the value of _xyz_. Where am I going wrong??
The whole error is that the object foodData isn't initialized properly. So, initialize it
A nice documentation - https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Classes/NSObject_Class/Reference/Reference.html
& fetching data from NSmutableDictionary
https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/objectForKey:
Remember the key that you use to compare in dictionary should have same casing (capital - small) as defined earlier. e.g You store an object for key 'example' but you can not retrieve it using ''Example' or 'EXAMPLE'. You can only use 'example' as defined earlier. And
You don't need to get arrays of keys from dictionary & fast-enumerate it
You can just get the object using objectForKey: method. Good luck.