What you're observing here is Mercator distortion. A distance of "50" in a mercator projection doesn't correspond to 50 meters on the real planet surface, unless you're at the Equator.
The circle drawn by your iOS map is correct: that's the 50 meter radius. What I suspect you did to create your second image was to project the point into a Mercator projection (according to the Proj4 you provided). Then you proceeded to create a buffer with radius 50 in the projected coordinate system. However, 50 Mercator units at latitude 40.61 corresponds to only about 37.96 meters in surface of the earth distance. So when you project that polygon back into latitude and longitude and plot it, that's what you see: a 38-meter circle.
One way to visualize this is to look at the full world map on Google Maps. Draw a circle of radius 50 pixels at the equator. And then draw another circle of radius 50 pixels over Greenland. On the map (in Mercator coordinates), those circles are the same size. But, if you know your Mercator projection, you know it distorts Greenland because Greenland is far away from the Equator, so your circle over Greenland is actually much smaller in real life than your circle above the equator. At 40 degrees latitude, the distortion isn't as severe, but it still is there.
If you want to correct this, it's pretty easy. The size distortion caused by the Mercator projection is proportional to the secant of the latitude. That is, 50 mercator units on the equator equals 50 meters, but 50 mercator units at latitude x (in radians), corresponds to 50 / sec(x) meters. So if you want a radius of 50 meters, multiply 50 by sec(latitude), and use that number as the radius in mercator coordinates. In RGeo-speak:
p_lonlat = GEOFACTORY.point(40.610355377197266, -75.38220214843749)
p_proj = p_lonlat.projection
buf_proj = p_proj.buffer(50.0 * (1 / Math.cos(p_lonlat.y / 180.0 * Math::PI)))
buf_lonlat = GEOFACTORY.unproject(buf_proj)