0

I've recently update j2objc from 0.9.4 to the latest version (0.9.8.2.1). Previous version generates all members as public, but since 0.9.6 private members are hidden by default. For some reasons I have to have access to some private members from other classes. There is a solution in release notes:

Note: --hide-private-members is now default, so that private fields and methods are no longer visible in public header files. If that breaks your project, either fix the illegal references, make those members non-private (since they aren't), or use the --no-hide-private-members flag.

I've tried to append this flag to my project, but had no success (I'm not able to change java code). I've tried to read j2objc --help, but there is no mention about this flag. So I wonder where have I set this flag to build the project with all public members as it was before?

I use makefile similar to described here (in documentation). Here is the part of it:

default: translate cycle_finder

clean:
    @rm -rf $(BUILD_DIR)
    @rm -rf $(J2OBJC_RESULT_DIR)
    @rm -f $(RETAIN_CYCLES)

$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.m
    $(J2OBJCC) -I$(BUILD_DIR) -c $? -o $@

translate: pre_translate $(J2OBJC_GENERATED_SOURCES)
    @if [ `cat $(JAVA_SOURCES) | wc -l` -ge 1 ] ; then \
      ./build_mappings.pl $(CALCULATOR_NEUTRAL_DIR) CN > $(JAVA_PACKAGE_MAPPINGS); \
      ./build_mappings.pl $(FOUNDATION_NEUTRAL_DIR) FN >> $(JAVA_PACKAGE_MAPPINGS); \
      ./build_mappings.pl $(CALCULATOR_NEUTRAL_TEST_DIR) CNT >> $(JAVA_PACKAGE_MAPPINGS); \
      ./build_mappings.pl $(FOUNDATION_NEUTRAL_TEST_DIR) FNT >> $(JAVA_PACKAGE_MAPPINGS); \
      $(J2OBJC) \
        --no-hide-private-members \
        -sourcepath $(SOURCE_DIR) \
        $(ADDITIONAL_CLASS_PATHS) -use-arc  \
        -d $(J2OBJC_RESULT_DIR) \
        --prefixes $(JAVA_PACKAGE_MAPPINGS) \
        `cat $(JAVA_SOURCES)` ; \
    fi

cycle_finder: pre_translate $(J2OBJC_GENERATED_SOURCES)
    -@if [ `cat $(JAVA_SOURCES) | wc -l` -ge 1 ] ; then \
      $(CYCLE_FINDER) \
        --no-hide-private-members \
        -sourcepath $(SOURCE_DIR) \
        -w $(WHITELIST_PATH) \
        $(ADDITIONAL_CLASS_PATHS) \
        `cat $(JAVA_SOURCES)` > $(RETAIN_CYCLES); \
    fi

$(J2OBJC_RESULT_DIR):
    @mkdir -p $(J2OBJC_RESULT_DIR)

$(BUILD_DIR):
    @mkdir -p $(BUILD_DIR)

pre_translate: $(J2OBJC_RESULT_DIR) $(BUILD_DIR)
    @rm -f $(JAVA_SOURCES)
    @touch $(JAVA_SOURCES)

$(J2OBJC_RESULT_DIR)/%.m $(J2OBJC_RESULT_DIR)/%.h: $(SOURCE_DIR)/%.java JavaBuild.make
    @echo $< >> $(JAVA_SOURCES)

Thanks for any help and suggestion.

Soberman
  • 2,556
  • 1
  • 19
  • 22
Accid Bright
  • 592
  • 5
  • 17

2 Answers2

0

The --no-hide-private-members flag was just a temporary one to give projects some time to update their accesses, and 0.9.4 was released over two years ago. The flag is present to allow builds to still work, but is now ignored.

Generally, private fields shouldn't be accessed by external classes regardless of what language their written in. At first we naively assumed that native developers would adhere to the accesses declared in the translated code, but we found that Xcode's code completion made using private members too tempting. Now private fields, methods, and classes are all now hidden in the .m file.

That said, there's nothing to stop you from working around access restrictions. To do that in Java (which should also work on Android):

Field f = TargetClass.class.getDeclaredField("privateField");
f.setAccessible(true);
// read or write f using reflection

To do it natively, you can try copying the class category inside the target class's generated .m file (where the field is declared) into your native file. AFAIK, there's nothing blocking multiple .m files from adding the same class category, as long as they don't differ. However, I haven't verified this works since "private fields shouldn't be accessed by external classes!" :-)

tball
  • 1,984
  • 11
  • 21
  • Tom - how about removing the flag? That way when the build is updated, someone is naturally forced to become aware of the change. Furthermore, it allows you to delete cruft that could otherwise stay around for a long time. – brunobowden Oct 26 '15 at 20:12
  • Tom, thanks for the explanation. So I see, I have to disturb Java developers to adopt their code for my current needs. – Accid Bright Oct 27 '15 at 11:53
0

The problem is that j2objc generates invalid Objective-C code. All private ivars can't be in a category and you end up with

error: instance variables may not be placed in class extension

for each private java variable you have.

Sometimes the code is 3rd party and there is nothing we can do to update access.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264