refactored from ObjC version