MKAnnotation to get address - objective-c

I noticed that the new map app has a feature that I need to implement in an app I am making. The feature is when the user drops a pin on a location, the address is shown as the subtitle of the annotation view. Does anyone know how to do that?

You should implement subtitle property in your custom annotation like:
// Geo.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface Geo : NSObject <MKAnnotation>
#property (nonatomic, strong) NSString* subtitle;
// Geo.m
#include "Geo.h"
#implementation Geo
- (NSString *)subtitle
{
return _subtitle; // Here you can reverse geocoding to get address from a CLLocationCoordinate2D object
};

Related

Can I change the type of a property in a class extension?

I wish to expose a property with a generic type in a public header, and then change its type to a more specific one in a private header. I'm using Clang, but though I'm able to change its read/write property, it doesn't accept a different type. So far this is what I tried:
A common client would import BKSystem.h:
#interface BKSystem : NSObject
#property(nonatomic, readonly) id<XYZWorker> worker;
#end
While a client for testing has access to internals by importing BKSystem+Testing.h:
#import "BKSystem.h"
#interface BKConfigurableWorker : NSObject<XYZWorker>
#property(nonatomic) BKConfiguration *config;
#end
#pragma mark -
#interface BKSystem ()
// Attempts to change worker to be writable and with a more specific type.
#property(nonatomic, readwrite) BKConfigurableWorker *worker;
#end
But on a testing client this is what I get:
#import "BKSystem+Testing.h"
BKSystem *system = [[BKSystem alloc] init];
// I am able to write to this property.
system.worker = [[BKConfigurableWorker alloc] init];
// ERROR: Property 'config' not found on object of type 'id<XYZWorker>'
system.worker.config = [[BKConfiguration alloc] init];
To accomplish what you're trying to do, I'd use BKWorker as a subclass rather than a protocol. See my example header file below:
#interface BKConfiguration : NSObject
#end
#interface BKWorker : NSObject
#property (nonatomic, strong, readonly) BKConfiguration *config;
#end
#interface BKConfigurableWorker : BKWorker
#property (nonatomic, strong, readwrite) BKConfiguration *config;
#end
Notice that the same property is declared again in the configurable worker, but as readwrite rather than readonly.
This produces the following results when used in an implementation:
Notice how the configurable worker can be written to but the standard one can not.
Hope this helps.

incompatible with type id<NSTextFieldDelegate>

I am getting new warning on my old OSX app. I am using OSX 10.10 and I am not quite sure where the problem is. Can someone help?
The actual warning is Property type 'id is incompatible with type id inherited from NSTextField
#import <Cocoa/Cocoa.h>
#import "HyperlinkTextFieldDelegate.h"
#interface HyperlinkTextField : NSTextField <NSTextFieldDelegate>
#property (assign) id <HyperlinkTextFieldDelegate> delegate; <--- warning showing up here
#end
The main implementation is
#interface HyperlinkTextField ()
#property (nonatomic, readonly) NSArray *hyperlinkInfos;
#property (nonatomic, readonly) NSTextView *textView;
- (void)_resetHyperlinkCursorRects;
#end
#define kHyperlinkInfoCharacterRangeKey #"range"
#define kHyperlinkInfoURLKey #"url"
#define kHyperlinkInfoRectKey #"rect"
#implementation HyperlinkTextField
#synthesize delegate;
And the delegate file is
#import <Foundation/Foundation.h>
#protocol HyperlinkTextFieldDelegate <NSObject>
- (void) barLinkClicked: (id) sender;
#end
NSTextField already has a delegate property, and it is typed as id<NSTextFieldDelegate>. Thus, your HyperinkTextField, which is a subclass of NSTextField, inherits this property, just as the error message clearly tells you. You cannot override this inherited property and type it as id<HyperlinkTextFieldDelegate> where that is a different type.

Compiler and/or Xcode errors unknown type and expected identifier. Import loop?

Edit2: I restructured all of my headers to have the #class as opposed to the #import language. All .m files now have #import. The problem as posted here seems to be fixed. There are some BAD ACCESS errors now, but while it may be all the same root problem, this manifestation is resolved
Edit: I just found out about something called an "import loop". I'm looking into this being the problem. If anyone has any info about this please let me know.
Unrelated changes are causing impossible errors- I assume there is something deeper or some mistake elsewhere in the program but I just want to confirm this is the case. I have 3 errors and have already rebuild the program in a different Xcode project. I have some code examples, but don't worry- they're (mostly) header files
Error 1
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "PixelSprite.h"
#import "HUDLayer.h"
#import "PixelCharacter.h"
/*typedef enum
{
GameSceneLayerTagGame = 1,
GameSceneLayerTagHUD
}GameSceneLayerTags;*/
#interface GameLayer : CCLayer {
}
#property (assign,readwrite) CGPoint heroStartPoint;
#property (nonatomic, retain) CCTMXTiledMap *tileMap;
#property (nonatomic, retain) CCTMXLayer *background;
#property (assign, readwrite) NSInteger scrollSpeed;
#property (assign, readwrite) PixelCharacter *heroCharacter;
The above line contains a compiler error: Unknown type name 'PixelCharacter'. I know that there is no misspelling. I have even go so far as to copy-paste names of classes and header files just to make sure
+(GameLayer *) sharedGameLayer;
-(id) init;
#end
Error 2
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "HUDButton.h"
#interface HUDLayer : CCLayer {
}
#property (readwrite,assign) CCArray* buttonsArray;
// Working with the buttons
-(void) addHUDButtonOfType:(NSString*)type inSlot:(int)slot;
-(void) addHUDButtonOfType:(NSString*)type;
-(void) removeHUDButton:(HUDButton*)button;
The above line contains a compiler error: Expected a type
This makes no sense since a type is clearly posted
-(void) removeHUDButtonOfType:(NSString*)type;
-(void) removeAllButtons;
-(void) buttonsQuery;
#end
Error 3
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
// Get touch location
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
// Verify that touch is on button
BOOL isTouchHandled = CGRectContainsPoint([buttonSprite boundingBox], location);
if (isTouchHandled) {
[buttonSprite setColor:ccRED];
SEL selector = NSSelectorFromString(actionMessage);
GameLayer* layer = [GameLayer sharedGameLayer];
PixelCharacter* heroCharacter = [layer heroCharacter];
The above line contains a compiler warning: incompatible pointer types initializing 'PixelCharacter*' with and expression of type 'int *'
[heroCharacter addToDoQueue:selector];
}
return isTouchHandled;
}
The issue was circular import dependencies.
Apparently, #import in the .h file can sometimes "cover up" problems by making the compiler think that all necessary headers are imported when really it depends on the compile order. The fix and best practice is to use
#class MyClass
in the header and
#import "MyClass.h"
in the .m

How can I make my MKMapView annotations show up?

I'm new to this, and I'm banging my head on a wall, so any help you can provide would be appreciated.
My app is downloading a series of coordinates and titles which I'm turning into MKAnnotations. I've implemented the MKAnnotation protocol well enough because it's stopped complaining about that, but here's the code:
Annotator.h:
#import <Foundation/Foundation.h>
#import "MapKit/Mapkit.h"
#interface Annotator : NSObject <MKAnnotation>
+ (Annotator *) createAnnotator:(CLLocationCoordinate2D *)coordinate
withTitle:(NSString *)title
andSubtitle:(NSString *)subtitle;
#property (nonatomic, strong) NSString *myTitle;
#property (nonatomic, strong) NSString *mySubtitle;
#property (nonatomic) CLLocationCoordinate2D *coordinate;
#end
Pretty boring so far. Here's Annotator.m:
#import "Annotator.h"
#implementation Annotator
#synthesize myTitle = _myTitle;
#synthesize mySubtitle = _mySubtitle;
#synthesize coordinate = _coordinate;
+ (Annotator *)createAnnotator:(CLLocationCoordinate2D *)coordinate
withTitle:(NSString *)title
andSubtitle:(NSString *)subtitle
{
Annotator *annotation = [[Annotator alloc] init];
annotation.myTitle = title;
annotation.mySubtitle = subtitle;
annotation.coordinate = coordinate;
return annotation;
}
- (NSString *)title
{
return self.myTitle;
}
- (NSString *)subtitle
{
return self.mySubtitle;
}
#end
Right now, I've got most of the other code in a central view controller, so as soon as the HTTP request returns with the data, I iterate through it, creating my MKAnnotation objects, and then do this for each one:
[self.territoryMap addAnnotation:locationPin];
...where self.territoryMap is an outlet to the MKMapView I dragged into my storyboard, and locationPin is the MKAnnotation object I created with my Annotator implementation above.
Some of the solutions I've looked at have MKMapViewDelegate methods in place, but it seems to me that they shouldn't be necessary, as I'm just looking for the default behavior. I put in one delegate that I found which allowed me to change the color of the user's location pin, but that's not what I'm worried about.
Is there something else I need to be doing? I'm confused! Thanks for whatever help you can provide!
You have to set the MapViews delegate. Then it should work fine.
Alternatively look into this: http://maybelost.com/2011/01/a-basic-mapview-and-annotation-tutorial/
It looks pretty much like that what you are trying to do!

NSObject subclass as a property

I want to use my class as a property in my project. The idea is that i have a class which contains all list ellements. The basic idea i show below in graph:
So i have a myContainerClass object, and i want to do in some other class:
#property (strong,nonatomic) MyContainerClass *obj;
and here i have error! I figure out that i can only use Foundations type as a #property. But Why? What is replacement for doing that (passing an object)?
No, you can use any class you like as a property
#property (nonatomic, strong) MyContainerClass* obj;
is perfectly legal provided that the compiler knows that MyContainerClass is a class. To do that in the header file, the best way is to use an #class forward declaration:
#class MyContainerClass;
#interface SomeOtherClass : NSObject
// method an property declarations
#property (nonatomic, strong) MyContainerClass* obj;
#end
And then include the header file in the implementation:
#import "MyContainerClass.h"
#implementation SomeOtherClass
#synthesize obj;
// other stuff
#end
What is the error you are getting? May be you are not importing MyContainerClass to where you want to use it.
#import "MyContainerClass.h"
Declare a category for an object that you want to add your property to:
#interface NSObject (MyContainerClassAdditions)
#property (nonatomic, strong) MyContainerClass *myContainerClass
#end
Then implement the setter and getter methods using objective c associated object trick:
#import <objc/runtime.h>
#implementation NSObject (MyContainerClassAdditions)
- (void)setMyContainerClass:(MyContainerClass *)myContainerClass {
objc_setAssociatedObject(self, "myContainerClass", myContainerClass, OBJC_ASSOCIATION_ASSIGN);
}
- (MyContainerClass *)myContainerClass {
return objc_getAssociatedObject(self, "myContainerClass");
}
#end