Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Moved all GIK-prefixed classes into a subfolder.

Added README and BSD license.
  • Loading branch information...
commit 358880271a1f4510f188b16976688152f8f237be 1 parent 40feb55
@GiK authored
View
1,529 AnimatedCallout.xcodeproj/gordon.pbxuser
1,060 additions, 469 deletions not shown
View
149 AnimatedCallout.xcodeproj/gordon.perspectivev3
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>ActivePerspectiveName</key>
- <string>Debug</string>
+ <string>Project</string>
<key>AllowedModules</key>
<array>
<dict>
@@ -197,49 +197,7 @@
<key>Notifications</key>
<array/>
<key>OpenEditors</key>
- <array>
- <dict>
- <key>Content</key>
- <dict>
- <key>PBXProjectModuleGUID</key>
- <string>F8BEF0FA130D6569000D5E50</string>
- <key>PBXProjectModuleLabel</key>
- <string>MapViewController.h</string>
- <key>PBXSplitModuleInNavigatorKey</key>
- <dict>
- <key>Split0</key>
- <dict>
- <key>PBXProjectModuleGUID</key>
- <string>F8BEF0FB130D6569000D5E50</string>
- <key>PBXProjectModuleLabel</key>
- <string>MapViewController.h</string>
- <key>_historyCapacity</key>
- <integer>0</integer>
- <key>bookmark</key>
- <string>F8BEF2FB130D9380000D5E50</string>
- <key>history</key>
- <array>
- <string>F8BEF0FC130D6569000D5E50</string>
- <string>F8BEF0FD130D6569000D5E50</string>
- </array>
- </dict>
- <key>SplitCount</key>
- <string>1</string>
- </dict>
- <key>StatusBarVisibility</key>
- <true/>
- </dict>
- <key>Geometry</key>
- <dict>
- <key>Frame</key>
- <string>{{0, 20}, {1131, 742}}</string>
- <key>PBXModuleWindowStatusBarHidden2</key>
- <false/>
- <key>RubberWindowFrame</key>
- <string>1482 -106 1131 783 1366 -256 1280 1024 </string>
- </dict>
- </dict>
- </array>
+ <array/>
<key>PerspectiveWidths</key>
<array>
<integer>1366</integer>
@@ -275,6 +233,8 @@
<key>Layout</key>
<array>
<dict>
+ <key>BecomeActive</key>
+ <true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXBottomSmartGroupGIDs</key>
@@ -322,14 +282,14 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
- <integer>5</integer>
+ <integer>8</integer>
<integer>2</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
- <string>{{0, 0}, {270, 648}}</string>
+ <string>{{0, 0}, {270, 1001}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@@ -339,12 +299,14 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 0}, {287, 666}}</string>
+ <string>{{0, 0}, {287, 1019}}</string>
<key>GroupTreeTableConfiguration</key>
<array>
<string>MainColumn</string>
<real>270</real>
</array>
+ <key>RubberWindowFrame</key>
+ <string>1194 358 1355 1060 0 0 2560 1418 </string>
</dict>
<key>Module</key>
<string>PBXSmartGroupTreeModule</string>
@@ -360,7 +322,7 @@
<key>PBXProjectModuleGUID</key>
<string>F862DD7B1309B7F9005CDAE3</string>
<key>PBXProjectModuleLabel</key>
- <string>GIKCalloutView.m</string>
+ <string>GIKCalloutContentView.m</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@@ -368,41 +330,41 @@
<key>PBXProjectModuleGUID</key>
<string>F862DD7C1309B7F9005CDAE3</string>
<key>PBXProjectModuleLabel</key>
- <string>GIKCalloutView.m</string>
+ <string>GIKCalloutContentView.m</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
- <string>F8BEF2FA130D9380000D5E50</string>
+ <string>F80D605A130DFC55009ED142</string>
<key>history</key>
<array>
<string>F822C552130A205A000F0385</string>
<string>F822C554130A205A000F0385</string>
<string>F822C598130A3760000F0385</string>
- <string>F862DF34130AE286005CDAE3</string>
- <string>F862DF38130AE286005CDAE3</string>
<string>F862E155130C1E8D005CDAE3</string>
- <string>F8BEF0E3130D6569000D5E50</string>
- <string>F8BEF0EA130D6569000D5E50</string>
- <string>F8BEF0EB130D6569000D5E50</string>
- <string>F8BEF0EC130D6569000D5E50</string>
- <string>F8BEF1B7130D70E8000D5E50</string>
- <string>F8BEF1B8130D70E8000D5E50</string>
- <string>F8BEF282130D89F2000D5E50</string>
- <string>F8BEF2AF130D8E2B000D5E50</string>
- <string>F8BEF2B0130D8E2B000D5E50</string>
- <string>F8BEF2B1130D8E2B000D5E50</string>
- <string>F8BEF2B2130D8E2B000D5E50</string>
- <string>F8BEF2B3130D8E2B000D5E50</string>
- <string>F8BEF2B5130D8E2B000D5E50</string>
- <string>F8BEF2B6130D8E2B000D5E50</string>
- <string>F8BEF2CC130D8E8D000D5E50</string>
- <string>F8BEF2CD130D8E8D000D5E50</string>
- <string>F8BEF2CE130D8E8D000D5E50</string>
- <string>F8BEF2D9130D90A1000D5E50</string>
<string>F8BEF2DA130D90A1000D5E50</string>
<string>F8BEF2DB130D90A1000D5E50</string>
- <string>F8BEF2E8130D9290000D5E50</string>
- <string>F8BEF2E9130D9290000D5E50</string>
+ <string>F8BEF319130D9635000D5E50</string>
+ <string>F8BEF340130DC589000D5E50</string>
+ <string>F8BEF341130DC589000D5E50</string>
+ <string>F8BEF343130DC589000D5E50</string>
+ <string>F8BEF345130DC589000D5E50</string>
+ <string>F8BEF347130DC589000D5E50</string>
+ <string>F8BEF348130DC589000D5E50</string>
+ <string>F8BEF349130DC589000D5E50</string>
+ <string>F8BEF34A130DC589000D5E50</string>
+ <string>F8BEF34B130DC589000D5E50</string>
+ <string>F8BEF34C130DC589000D5E50</string>
+ <string>F8BEF34D130DC589000D5E50</string>
+ <string>F8BEF34E130DC589000D5E50</string>
+ <string>F8BEF34F130DC589000D5E50</string>
+ <string>F8BEF350130DC589000D5E50</string>
+ <string>F8BEF351130DC589000D5E50</string>
+ <string>F8BEF35A130DCBDE000D5E50</string>
+ <string>F8BEF35B130DCBDE000D5E50</string>
+ <string>F8BEF35C130DCBDE000D5E50</string>
+ <string>F8BEF35D130DCBDE000D5E50</string>
+ <string>F80D604D130DD738009ED142</string>
+ <string>F80D604F130DD738009ED142</string>
</array>
</dict>
<key>SplitCount</key>
@@ -416,16 +378,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 0}, {1074, 374}}</string>
+ <string>{{0, 0}, {1063, 1014}}</string>
+ <key>RubberWindowFrame</key>
+ <string>1194 358 1355 1060 0 0 2560 1418 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
- <string>374pt</string>
+ <string>1014pt</string>
</dict>
<dict>
<key>Proportion</key>
- <string>287pt</string>
+ <string>0pt</string>
<key>Tabs</key>
<array>
<dict>
@@ -439,7 +403,9 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{10, 27}, {1074, 171}}</string>
+ <string>{{10, 27}, {1063, -27}}</string>
+ <key>RubberWindowFrame</key>
+ <string>1194 358 1355 1060 0 0 2560 1418 </string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@@ -455,7 +421,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{10, 27}, {1074, 260}}</string>
+ <string>{{0, 0}, {614, 336}}</string>
</dict>
<key>Module</key>
<string>PBXProjectFindModule</string>
@@ -493,7 +459,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{10, 27}, {1074, -27}}</string>
+ <string>{{0, 0}, {568, 405}}</string>
</dict>
<key>Module</key>
<string>PBXBuildResultsModule</string>
@@ -502,7 +468,7 @@
</dict>
</array>
<key>Proportion</key>
- <string>1074pt</string>
+ <string>1063pt</string>
</dict>
</array>
<key>Name</key>
@@ -521,11 +487,11 @@
</array>
<key>TableOfContents</key>
<array>
- <string>F8BEF0F2130D6569000D5E50</string>
+ <string>F80D605B130DFC55009ED142</string>
<string>1CA23ED40692098700951B8B</string>
- <string>F8BEF0F3130D6569000D5E50</string>
+ <string>F80D605C130DFC55009ED142</string>
<string>F862DD7B1309B7F9005CDAE3</string>
- <string>F8BEF0F4130D6569000D5E50</string>
+ <string>F80D605D130DFC55009ED142</string>
<string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string>
@@ -576,8 +542,6 @@
<dict>
<key>Frame</key>
<string>{{0, 0}, {1366, 257}}</string>
- <key>RubberWindowFrame</key>
- <string>0 39 1366 707 0 0 1366 746 </string>
</dict>
<key>Module</key>
<string>PBXDebugCLIModule</string>
@@ -652,11 +616,7 @@
</array>
<key>Frame</key>
<string>{{0, 167}, {511, 237}}</string>
- <key>RubberWindowFrame</key>
- <string>0 39 1366 707 0 0 1366 746 </string>
</dict>
- <key>RubberWindowFrame</key>
- <string>0 39 1366 707 0 0 1366 746 </string>
</dict>
<key>Module</key>
<string>PBXDebugSessionModule</string>
@@ -720,15 +680,10 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
- <string>F8BEF2FC130D9380000D5E50</string>
- <string>F862DE181309BD05005CDAE3</string>
- <string>F8BEF100130D656A000D5E50</string>
- <string>F8BEF101130D656A000D5E50</string>
- <string>F8BEF0FA130D6569000D5E50</string>
- <string>/Users/gordon/Developer/Xcode/GiK/AnimatedCallout/AnimatedCallout.xcodeproj</string>
+ <string>/Users/Gordon/Developer/Xcode/GiK/gik-animated-callout/AnimatedCallout.xcodeproj</string>
</array>
<key>WindowString</key>
- <string>0 39 1366 707 0 0 1366 746 </string>
+ <string>1194 358 1355 1060 0 0 2560 1418 </string>
<key>WindowToolsV3</key>
<array>
<dict>
@@ -1537,7 +1492,7 @@
<key>Frame</key>
<string>{{0, 0}, {897, 681}}</string>
<key>RubberWindowFrame</key>
- <string>1749 46 897 722 1366 -256 1280 1024 </string>
+ <string>1749 46 897 722 0 0 1366 746 </string>
<key>XCRefactoringSplitViewLowerHeight</key>
<real>296</real>
<key>XCRefactoringSplitViewTotalHeight</key>
@@ -1568,7 +1523,7 @@
<string>F862DE171309BD05005CDAE3</string>
</array>
<key>WindowString</key>
- <string>1749 46 897 722 1366 -256 1280 1024 </string>
+ <string>1749 46 897 722 0 0 1366 746 </string>
<key>WindowToolGUID</key>
<string>F862DE181309BD05005CDAE3</string>
<key>WindowToolIsVisible</key>
View
96 AnimatedCallout.xcodeproj/project.pbxproj 100755 → 100644
@@ -13,7 +13,6 @@
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; };
28D7ACF80DDB3853001CB0EB /* MapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* MapViewController.m */; };
- F822C525130A1004000F0385 /* GIKCalloutContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = F822C524130A1004000F0385 /* GIKCalloutContentView.m */; };
F822C570130A2AF3000F0385 /* Hotels.plist in Resources */ = {isa = PBXBuildFile; fileRef = F822C56F130A2AF3000F0385 /* Hotels.plist */; };
F822C579130A342A000F0385 /* HotelAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = F822C578130A342A000F0385 /* HotelAnnotation.m */; };
F822C580130A3476000F0385 /* Hotel.m in Sources */ = {isa = PBXBuildFile; fileRef = F822C57F130A3476000F0385 /* Hotel.m */; };
@@ -35,15 +34,17 @@
F8320A7D130B79A400CB5810 /* CalloutTableBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = F8320A7C130B79A400CB5810 /* CalloutTableBackground.png */; };
F862DDB11309BB06005CDAE3 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F862DDB01309BB06005CDAE3 /* MapKit.framework */; };
F862DDF01309BB7B005CDAE3 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F862DDEF1309BB7B005CDAE3 /* CoreLocation.framework */; };
- F862DE251309C2CB005CDAE3 /* GIKCalloutAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DE241309C2CB005CDAE3 /* GIKCalloutAnnotation.m */; };
- F862DE2A1309C489005CDAE3 /* GIKCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DE291309C489005CDAE3 /* GIKCalloutView.m */; };
F862DE991309DC61005CDAE3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F862DE981309DC61005CDAE3 /* QuartzCore.framework */; };
- F862DF01130AC465005CDAE3 /* GIKAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DF00130AC465005CDAE3 /* GIKAnnotation.m */; };
- F862DF09130AC6A3005CDAE3 /* GIKPinAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DF08130AC6A3005CDAE3 /* GIKPinAnnotationView.m */; };
- F862DF4F130AE683005CDAE3 /* GIKAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DF4E130AE683005CDAE3 /* GIKAnnotationView.m */; };
F862DF6E130AFB57005CDAE3 /* HotelDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F862DF6D130AFB57005CDAE3 /* HotelDetailViewController.m */; };
- F8BEF0C2130D53FF000D5E50 /* GIKMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F8BEF0C1130D53FF000D5E50 /* GIKMapViewController.m */; };
F8BEF12D130D6AD3000D5E50 /* GIKMapView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F8BEF12C130D6AD3000D5E50 /* GIKMapView.xib */; };
+ F8E52766130EB5BC002BC098 /* GIKAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E52759130EB5BC002BC098 /* GIKAnnotation.m */; };
+ F8E52767130EB5BC002BC098 /* GIKAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E5275B130EB5BC002BC098 /* GIKAnnotationView.m */; };
+ F8E52768130EB5BC002BC098 /* GIKCalloutAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E5275D130EB5BC002BC098 /* GIKCalloutAnnotation.m */; };
+ F8E52769130EB5BC002BC098 /* GIKCalloutContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E5275F130EB5BC002BC098 /* GIKCalloutContentView.m */; };
+ F8E5276A130EB5BC002BC098 /* GIKCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E52761130EB5BC002BC098 /* GIKCalloutView.m */; };
+ F8E5276B130EB5BC002BC098 /* GIKMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E52763130EB5BC002BC098 /* GIKMapViewController.m */; };
+ F8E5276C130EB5BC002BC098 /* GIKPinAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E52765130EB5BC002BC098 /* GIKPinAnnotationView.m */; };
+ F8E5278B130F1273002BC098 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = F8E5278A130F1273002BC098 /* LICENSE */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -58,8 +59,6 @@
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
32CA4F630368D1EE00C91783 /* AnimatedCallout_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedCallout_Prefix.pch; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* AnimatedCallout-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AnimatedCallout-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
- F822C523130A1004000F0385 /* GIKCalloutContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutContentView.h; sourceTree = "<group>"; };
- F822C524130A1004000F0385 /* GIKCalloutContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutContentView.m; sourceTree = "<group>"; };
F822C56F130A2AF3000F0385 /* Hotels.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Hotels.plist; sourceTree = "<group>"; };
F822C577130A342A000F0385 /* HotelAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HotelAnnotation.h; sourceTree = "<group>"; };
F822C578130A342A000F0385 /* HotelAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HotelAnnotation.m; sourceTree = "<group>"; };
@@ -83,22 +82,26 @@
F8320A7C130B79A400CB5810 /* CalloutTableBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalloutTableBackground.png; sourceTree = "<group>"; };
F862DDB01309BB06005CDAE3 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; };
F862DDEF1309BB7B005CDAE3 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
- F862DE231309C2CB005CDAE3 /* GIKCalloutAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutAnnotation.h; sourceTree = "<group>"; };
- F862DE241309C2CB005CDAE3 /* GIKCalloutAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutAnnotation.m; sourceTree = "<group>"; };
- F862DE281309C489005CDAE3 /* GIKCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutView.h; sourceTree = "<group>"; };
- F862DE291309C489005CDAE3 /* GIKCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutView.m; sourceTree = "<group>"; };
F862DE981309DC61005CDAE3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
- F862DEFF130AC465005CDAE3 /* GIKAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKAnnotation.h; sourceTree = "<group>"; };
- F862DF00130AC465005CDAE3 /* GIKAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKAnnotation.m; sourceTree = "<group>"; };
- F862DF07130AC6A3005CDAE3 /* GIKPinAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKPinAnnotationView.h; sourceTree = "<group>"; };
- F862DF08130AC6A3005CDAE3 /* GIKPinAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKPinAnnotationView.m; sourceTree = "<group>"; };
- F862DF4D130AE683005CDAE3 /* GIKAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKAnnotationView.h; sourceTree = "<group>"; };
- F862DF4E130AE683005CDAE3 /* GIKAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKAnnotationView.m; sourceTree = "<group>"; };
F862DF6C130AFB57005CDAE3 /* HotelDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HotelDetailViewController.h; sourceTree = "<group>"; };
F862DF6D130AFB57005CDAE3 /* HotelDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HotelDetailViewController.m; sourceTree = "<group>"; };
- F8BEF0C0130D53FF000D5E50 /* GIKMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKMapViewController.h; sourceTree = "<group>"; };
- F8BEF0C1130D53FF000D5E50 /* GIKMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKMapViewController.m; sourceTree = "<group>"; };
F8BEF12C130D6AD3000D5E50 /* GIKMapView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GIKMapView.xib; sourceTree = "<group>"; };
+ F8E52758130EB5BC002BC098 /* GIKAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKAnnotation.h; sourceTree = "<group>"; };
+ F8E52759130EB5BC002BC098 /* GIKAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKAnnotation.m; sourceTree = "<group>"; };
+ F8E5275A130EB5BC002BC098 /* GIKAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKAnnotationView.h; sourceTree = "<group>"; };
+ F8E5275B130EB5BC002BC098 /* GIKAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKAnnotationView.m; sourceTree = "<group>"; };
+ F8E5275C130EB5BC002BC098 /* GIKCalloutAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutAnnotation.h; sourceTree = "<group>"; };
+ F8E5275D130EB5BC002BC098 /* GIKCalloutAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutAnnotation.m; sourceTree = "<group>"; };
+ F8E5275E130EB5BC002BC098 /* GIKCalloutContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutContentView.h; sourceTree = "<group>"; };
+ F8E5275F130EB5BC002BC098 /* GIKCalloutContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutContentView.m; sourceTree = "<group>"; };
+ F8E52760130EB5BC002BC098 /* GIKCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKCalloutView.h; sourceTree = "<group>"; };
+ F8E52761130EB5BC002BC098 /* GIKCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKCalloutView.m; sourceTree = "<group>"; };
+ F8E52762130EB5BC002BC098 /* GIKMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKMapViewController.h; sourceTree = "<group>"; };
+ F8E52763130EB5BC002BC098 /* GIKMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKMapViewController.m; sourceTree = "<group>"; };
+ F8E52764130EB5BC002BC098 /* GIKPinAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKPinAnnotationView.h; sourceTree = "<group>"; };
+ F8E52765130EB5BC002BC098 /* GIKPinAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKPinAnnotationView.m; sourceTree = "<group>"; };
+ F8E5277B130EB7B4002BC098 /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.markdown; sourceTree = "<group>"; wrapsLines = 1; };
+ F8E5278A130F1273002BC098 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; wrapsLines = 1; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -121,7 +124,7 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
- F862DE1C1309BD45005CDAE3 /* GIK Map Classes */,
+ F8E52757130EB5BC002BC098 /* GIK */,
1D3623240D0F684500981E51 /* AnimatedCalloutAppDelegate.h */,
1D3623250D0F684500981E51 /* AnimatedCalloutAppDelegate.m */,
28D7ACF60DDB3853001CB0EB /* MapViewController.h */,
@@ -152,6 +155,8 @@
29B97317FDCFA39411CA2CEA /* Resources */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
+ F8E5277B130EB7B4002BC098 /* README.markdown */,
+ F8E5278A130F1273002BC098 /* LICENSE */,
);
name = CustomTemplate;
sourceTree = "<group>";
@@ -222,25 +227,25 @@
path = Resources/NIBs;
sourceTree = "<group>";
};
- F862DE1C1309BD45005CDAE3 /* GIK Map Classes */ = {
+ F8E52757130EB5BC002BC098 /* GIK */ = {
isa = PBXGroup;
children = (
- F862DE231309C2CB005CDAE3 /* GIKCalloutAnnotation.h */,
- F862DE241309C2CB005CDAE3 /* GIKCalloutAnnotation.m */,
- F862DE281309C489005CDAE3 /* GIKCalloutView.h */,
- F862DE291309C489005CDAE3 /* GIKCalloutView.m */,
- F822C523130A1004000F0385 /* GIKCalloutContentView.h */,
- F822C524130A1004000F0385 /* GIKCalloutContentView.m */,
- F862DEFF130AC465005CDAE3 /* GIKAnnotation.h */,
- F862DF00130AC465005CDAE3 /* GIKAnnotation.m */,
- F862DF07130AC6A3005CDAE3 /* GIKPinAnnotationView.h */,
- F862DF08130AC6A3005CDAE3 /* GIKPinAnnotationView.m */,
- F862DF4D130AE683005CDAE3 /* GIKAnnotationView.h */,
- F862DF4E130AE683005CDAE3 /* GIKAnnotationView.m */,
- F8BEF0C0130D53FF000D5E50 /* GIKMapViewController.h */,
- F8BEF0C1130D53FF000D5E50 /* GIKMapViewController.m */,
+ F8E52758130EB5BC002BC098 /* GIKAnnotation.h */,
+ F8E52759130EB5BC002BC098 /* GIKAnnotation.m */,
+ F8E5275A130EB5BC002BC098 /* GIKAnnotationView.h */,
+ F8E5275B130EB5BC002BC098 /* GIKAnnotationView.m */,
+ F8E5275C130EB5BC002BC098 /* GIKCalloutAnnotation.h */,
+ F8E5275D130EB5BC002BC098 /* GIKCalloutAnnotation.m */,
+ F8E5275E130EB5BC002BC098 /* GIKCalloutContentView.h */,
+ F8E5275F130EB5BC002BC098 /* GIKCalloutContentView.m */,
+ F8E52760130EB5BC002BC098 /* GIKCalloutView.h */,
+ F8E52761130EB5BC002BC098 /* GIKCalloutView.m */,
+ F8E52762130EB5BC002BC098 /* GIKMapViewController.h */,
+ F8E52763130EB5BC002BC098 /* GIKMapViewController.m */,
+ F8E52764130EB5BC002BC098 /* GIKPinAnnotationView.h */,
+ F8E52765130EB5BC002BC098 /* GIKPinAnnotationView.m */,
);
- name = "GIK Map Classes";
+ path = GIK;
sourceTree = "<group>";
};
/* End PBXGroup section */
@@ -310,6 +315,7 @@
F8320A29130B3F8B00CB5810 /* Button_DisclosureAccessory.png in Resources */,
F8320A7D130B79A400CB5810 /* CalloutTableBackground.png in Resources */,
F8BEF12D130D6AD3000D5E50 /* GIKMapView.xib in Resources */,
+ F8E5278B130F1273002BC098 /* LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -323,16 +329,16 @@
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
1D3623260D0F684500981E51 /* AnimatedCalloutAppDelegate.m in Sources */,
28D7ACF80DDB3853001CB0EB /* MapViewController.m in Sources */,
- F862DE251309C2CB005CDAE3 /* GIKCalloutAnnotation.m in Sources */,
- F862DE2A1309C489005CDAE3 /* GIKCalloutView.m in Sources */,
- F822C525130A1004000F0385 /* GIKCalloutContentView.m in Sources */,
F822C579130A342A000F0385 /* HotelAnnotation.m in Sources */,
F822C580130A3476000F0385 /* Hotel.m in Sources */,
- F862DF01130AC465005CDAE3 /* GIKAnnotation.m in Sources */,
- F862DF09130AC6A3005CDAE3 /* GIKPinAnnotationView.m in Sources */,
- F862DF4F130AE683005CDAE3 /* GIKAnnotationView.m in Sources */,
F862DF6E130AFB57005CDAE3 /* HotelDetailViewController.m in Sources */,
- F8BEF0C2130D53FF000D5E50 /* GIKMapViewController.m in Sources */,
+ F8E52766130EB5BC002BC098 /* GIKAnnotation.m in Sources */,
+ F8E52767130EB5BC002BC098 /* GIKAnnotationView.m in Sources */,
+ F8E52768130EB5BC002BC098 /* GIKCalloutAnnotation.m in Sources */,
+ F8E52769130EB5BC002BC098 /* GIKCalloutContentView.m in Sources */,
+ F8E5276A130EB5BC002BC098 /* GIKCalloutView.m in Sources */,
+ F8E5276B130EB5BC002BC098 /* GIKMapViewController.m in Sources */,
+ F8E5276C130EB5BC002BC098 /* GIKPinAnnotationView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
0  Classes/GIKAnnotation.h → Classes/GIK/GIKAnnotation.h
File renamed without changes
View
0  Classes/GIKAnnotation.m → Classes/GIK/GIKAnnotation.m
File renamed without changes
View
0  Classes/GIKAnnotationView.h → Classes/GIK/GIKAnnotationView.h
File renamed without changes
View
0  Classes/GIKAnnotationView.m → Classes/GIK/GIKAnnotationView.m
File renamed without changes
View
2  Classes/GIKCalloutAnnotation.h → Classes/GIK/GIKCalloutAnnotation.h
@@ -6,7 +6,7 @@
// Copyright 2011 GeeksInKilts. All rights reserved.
//
-// Custom MKAnnotation object which is used to anchor the custom annotation view (GIKCalloutView) at the same coordinate as a selected pin.
+// MKAnnotation object which is used to anchor the custom annotation view (GIKCalloutView) at the same coordinate as a selected pin.
#import <MapKit/MapKit.h>
View
0  Classes/GIKCalloutAnnotation.m → Classes/GIK/GIKCalloutAnnotation.m
File renamed without changes
View
0  Classes/GIKCalloutContentView.h → Classes/GIK/GIKCalloutContentView.h
File renamed without changes
View
0  Classes/GIKCalloutContentView.m → Classes/GIK/GIKCalloutContentView.m
File renamed without changes
View
2  Classes/GIKCalloutView.h → Classes/GIK/GIKCalloutView.h
@@ -7,6 +7,8 @@
//
// Subclass of MKAnnotationView which holds our custom view.
+// Inspired by the work of James Rantanen and his custom map annotations:
+// http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
View
24 Classes/GIKCalloutView.m → Classes/GIK/GIKCalloutView.m
@@ -140,17 +140,22 @@ - (void)calculateOffsets {
self.sideArrowVerticalOffset = [self convertPoint:self.parentAnnotationView.frame.origin fromView:self.parentAnnotationView.superview].y;
+
if (fabs(distanceFromCenter) < (roundf(frameWidth/2) - arrowOffset)) {
- // Keep callout centered on map, but adjust the bottom arrow's origin.
+ // The parent pin is close to the center, the callout bubble will be drawn centered on the map.
+ // The down-arrow will be offset to the left or right of center, depending on the location of the pin.
horizontalOffset = distanceFromCenter;
self.bottomArrowHorizontalOffset = roundf(frameWidth/2) - distanceFromCenter - BOTTOM_ARROW_CENTER;
}
else {
+ // The parent pin far enough to the left or right of center that the callout bubble can't be drawn in the center of the map.
if (distanceFromCenter > 0) {
+ // The down-arrow will be offset to the left of the bubble.
horizontalOffset = roundf(frameWidth/2) - arrowOffset;
self.bottomArrowHorizontalOffset = SIDE_WIDTH + SIDE_INSET;
}
else {
+ // The down-arrow will be offset to the right of the bubble.
horizontalOffset = - (roundf(frameWidth/2) - arrowOffset);
self.bottomArrowHorizontalOffset = frameWidth - SIDE_WIDTH - SIDE_INSET - BOTTOM_ARROW_WIDTH;
}
@@ -166,6 +171,8 @@ - (void)setAnnotation:(id <MKAnnotation>)annotation {
if (annotation != nil && self.parentAnnotationView != nil) {
self.parentOrigin = [self.mapView convertPoint:self.parentAnnotationView.frame.origin fromView:self.parentAnnotationView.superview];
self.calloutMode = CalloutModeDefault;
+
+ // Forces the arrow to be reset if it was cached.
self.bottomArrow.image = [self arrowForFrame:0 orientation:ArrowDown];
[self calculateOffsets];
}
@@ -175,6 +182,7 @@ - (void)setAnnotation:(id <MKAnnotation>)annotation {
#pragma mark -
#pragma mark Callout layout & animation
+// Grab an arrow subimage from the respective image atlases.
- (UIImage *)arrowForFrame:(NSUInteger)frameNumber orientation:(ArrowOrientation)orientation {
UIImage *arrowSourceImage = nil;
CGSize subimageSize = CGSizeZero;
@@ -199,6 +207,7 @@ - (UIImage *)arrowForFrame:(NSUInteger)frameNumber orientation:(ArrowOrientation
CFRelease(cgArrow);
if (orientation == ArrowRight) {
+ // Use UIImage scale property to flip the image horizontally.
return [UIImage imageWithCGImage:theArrow.CGImage scale:theArrow.scale orientation:UIImageOrientationUpMirrored];
}
@@ -289,6 +298,9 @@ - (void)displayDetailCallout {
}
CGRect newFrame = CGRectMake(newCalloutOrigin.x, newCalloutOrigin.y, newFrameSize.width, self.bounds.size.height);
+
+ // When the CADisplayLink is added to the animation's run loop, it will draw a new image for the bottom arrow.
+ // The default frame rate matches the device's refresh rate.
self.animationDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateBottomArrowImage)];
self.horizontalAnimationTick = 0;
@@ -298,18 +310,24 @@ - (void)displayDetailCallout {
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionLayoutSubviews
animations:^{
+ //
// First, animate the width of the callout to match the detail view's width.
+ //
[self.animationDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[self setFrame:newFrame];
}
completion:^ (BOOL finished) {
self.calloutMode = CalloutModeDetail;
[self.animationDisplayLink invalidate];
+
+ // Draw a new image for the side arrow with every tick of the refresh rate.
self.animationDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateSideArrowImage)];
CGRect expandedFrame = self.frame;
expandedFrame.size.height = self.bounds.size.height + newFrameSize.height + BOTTOM_INSET;
expandedFrame.origin.y = self.parentAnnotationView.frame.origin.y - roundf(expandedFrame.size.height/2) + SIDE_ARROW_CENTER;
+ // Re-set the centerOffset to the left or right side of the annotation pin.
+ // This ensures that the expanded callout will stay in position if the map's region property changes.
if (self.calloutBias == LeftBias) {
self.centerOffset = CGPointMake(-(roundf(expandedFrame.size.width/2)) - 16.0f, -16.0f);
}
@@ -321,9 +339,11 @@ - (void)displayDetailCallout {
[UIView animateWithDuration:0.3
delay:0.0
- options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionLayoutSubviews
+ options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionLayoutSubviews
animations:^{
+ //
// Second, animate the height of the callout to match the detail view's height.
+ //
[self.animationDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[self setFrame:expandedFrame];
}
View
0  Classes/GIKMapViewController.h → Classes/GIK/GIKMapViewController.h
File renamed without changes
View
0  Classes/GIKMapViewController.m → Classes/GIK/GIKMapViewController.m
File renamed without changes
View
0  Classes/GIKPinAnnotationView.h → Classes/GIK/GIKPinAnnotationView.h
File renamed without changes
View
0  Classes/GIKPinAnnotationView.m → Classes/GIK/GIKPinAnnotationView.m
File renamed without changes
View
9 LICENSE
@@ -0,0 +1,9 @@
+Copyright (c) 2011, Geeks In Kilts
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+Neither the name of Geeks In Kilts nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
132 README.markdown
@@ -0,0 +1,132 @@
+GIKAnimatedCallout
+==================
+
+GIKAnimatedCallout demonstrates the use of an `MKAnnotationView` subclass to provide functionality similar to the callouts in Maps.app on iPad.
+
+---
+Note
+----
+
+The project will build and run on an iPad running a minimum of iOS 4.2.
+
+It is not intended to run as-is on an iPhone or iPod touch. I recommend sticking with Apple's approach of handling callouts on those devices. That being said, parts of `GIKCalloutView` could be canabalised to provide a variable-height callout on smaller iOS devices if needed.
+
+---
+Background
+----------
+
+Maps.app on iPad is an example of Apple keeping the good APIs for themselves. If you've used it, you're certain to have seen the default callout bubble slide to the side of a selected pin and then expand to reveal a `UITableView` embedded within. Not only that, but the arrow that points to the pin animates once you've selected the accessory button:
+
+- the initial down arrow appears to shrink into the callout bubble
+- an arrow pointing left or right appears to grow out of the expanded callout
+
+Keeping the detail table anchored to the pin is a great user experience. And it's all done using private API.
+
+This project is my attempt to reproduce that functionality using publicly available API.
+
+Portions of [James Rantanen's][ref] work on custom map annotations were adapted for this project, specifically using a second `MKAnnotation` object and `MKAnnotationView` to display the custom callout bubble.
+
+ [ref]: http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/
+
+
+---
+Packing List
+------------
+
+* `GIKMapViewController`
+
+ `UIViewController` subclass which implements `MKMapViewDelegate`. File's Owner for `GIKMapView.xib`. Subclass this in your own map controller and adopt the data source protocol, `GIKCalloutDetailDataSource`.
+
+ In your subclass of `GIKMapViewController`, override the `-init` method to call `super`'s `-initWithNibName:bundle:`, providing `GIKMapView` as the nib name.
+
+ The delegate method `-detailController:detailForAnnotation:` is used to set the data object of your detail view controller (in this example, `HotelDetailViewController`).
+
+
+* `GIKAnnotation`
+
+ In `MapKit`, each pin object is backed by an annotation and an annotation view. An annotation is an invisible marker which corresponds to a latitude and longitude on the map. The annotation view is the visual representation of that marker, typically that of a pin.
+
+ Your annotation objects which will display a custom callout should subclass `GIKAnnotation`.
+
+ `GIKAnnotationView` and `GIKPinAnnotationView` are `GIKAnnotation`'s corresponding annotation views.
+
+ In this sample project, `HotelAnnotation` subclasses `GIKAnnotation`. The `title` property is overridden to return the hotel's name.
+
+
+* `GIKPinAnnotationView`
+
+ Subclass of `MKPinAnnotationView` used to provide a standard pin icon.
+
+ If a map view detects a touch which isn't with the bounds of an `MKAnnotationView`, the currently selected annotation view will be deselected and its callout dismissed. The `selectionEnabled` property is used to allow or prevent the map view from deselecting the pin annotation view. This is important when touches are detected on the custom callout annotation view.
+
+
+* `GIKAnnotationView`
+
+ Subclass of `MKAnnotationView` which can display a custom image instead of a standard pin icon and has a property called `selectionEnabled` to manage the selection state of the annotation view.
+
+
+* `GIKCalloutAnnotation`
+
+ When the user taps a pin, the default behaviour is to show a callout bubble (if `canShowCallout` is `YES`). There is no public API to allow customisation of the standard callout bubble beyond setting the `leftCalloutAccessoryView` and `rightCalloutAccessoryView` properties in `MKAnnotationView`. Therefore, an instance of `GIKCalloutAnnotation` is added to the map at the same coordinates as the selected pin, and it's this that's used to anchor the custom view to the pin.
+
+ When the map view asks its delegate to provide an annotation view for `GIKCalloutAnnotation`, it's given an instance of `GIKCalloutView`.
+
+
+* `GIKCalloutView`
+
+ Subclass of `MKAnnotationView` which represents the callout bubble. It has two states:
+
+ 1. `CalloutModeDefault` has the same appearance as a standard map callout.
+ 2. `CalloutModeDetail` has the same appearance as the custom callout in Maps.app on iPad.
+
+ The `calloutContentView` property is the container view for the callout, which is defined in `GIKCalloutContentView`. The content view is assigned in `GIKMapViewController`'s `MKMapViewDelegate` method `mapView:viewForAnnotation:`.
+
+ Adopts the `GIKCalloutContentViewDelegate` protocol, used to receive messages related to `UIGestureRecognizer` touch events sent from the content view.
+
+
+* `GIKCalloutContentView`
+
+ A simple `UIView` subclass which comprises the label, accessory view(s), and detail view subviews of `GIKCalloutView`.
+
+ Declares the `GIKCalloutContentViewDelegate` protocol to notify the callout view of certain `UIGestureRecognizer` touch events.
+
+
+---
+In Use
+------
+
+Create a subclass of `GIKMapViewController`. Adopt the `GIKCalloutDetailDataSource` protocol.
+
+In the `detailController:detailForAnnotation:` delegate method, provide a data object from your model which will be displayed in the detail controller. See the sample `MapViewController` for an example.
+
+In the sample, `HotelDetailViewController` is a view controller whose `UITableView` is added to `GIKCalloutContentView` detail view.
+
+Finally, create a subclass of `GIKAnnotation` which will be the `MKAnnotation` tied to a pin icon. In the sample, `HotelAnnotation` has a `hotel` instance variable. This is assigned in `MapViewController`'s `showAnnotations` method - when annotations are added to the map view.
+
+
+---
+//TODO:
+-------
+
+* `GIKCalloutView`
+
+ Add a method to adjust the map's on-screen region when a callout is drawn outside the bounds of the map. I have this in a project I'm working on at the moment, but it needs some work.
+
+* `GIKCalloutContentView`
+
+ Add a left accessory view and subtext label.
+
+* General
+
+ Fix some issues with touch handling on the sample's table view.
+
+ Attempting to scroll the table view in the simulator just plain up doesn't work, and will result in the parent annotation view being deselected. It seems that the simulator interprets any gesture as a tap.
+
+ Test different detail controllers, such as tiled scrollview, image browser, etc.
+
+
+---
+Contact
+-------
+
+Twitter: [@gordonhughes](http://twitter.com/gordonhughes)
Please sign in to comment.
Something went wrong with that request. Please try again.