Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Wrong .pyui file is getting loaded in XCode
-
I'm getting this error when building in Xcode.
Don't know if it has anything to do with that I have to use the code below (for iOS 8 issues).
import scene import os def find_bundled_files(file_extension='.pyui', exclude_dirs=('pylib', 'pylib_ext', 'Documentation', 'Textures')): found = [] # Use a built-in image's path as a starting point (use a different one if you've removed this from your project): dummy_img_path = scene.get_image_path('Test_Lenna') bundle_path = os.path.split(os.path.split(dummy_img_path)[0])[0] for path, dirs, files in os.walk(bundle_path): # Remove excluded directory names from the search (not required, but makes it faster): for excluded in exclude_dirs: try: dirs.remove(excluded) except: pass for filename in files: ext = os.path.splitext(filename)[1] if ext == file_extension: full_path = os.path.join(path, filename) found.append(full_path) return found ui_files = find_bundled_files() w, h = ui.get_screen_size() root_view = ui.load_view(find_bundled_files()[0]) root_view['namefield'].clear_button_mode = 'while_editing' root_view['namefield'].text = read_username() root_view.background_color = (0, 0.02, 0.1) scene_view = SceneView() scene_view.frame = (0, 0, w, h) scene_view.scene = Game() root_view.present(orientations=['portrait'], hide_title_bar=True )
-
In your .pyui file, do you really have a textfield named 'namefield'?
-
Yes.
-
Is
len(ui_files)
>1? -
Nope!
-
On the line after
ui.load_view()
put:
print([sv.name for sv in root_view.subviews])
-
Everything is listed EXCEPT for the textfield, here's my .pyui file to prove it:
[{"class":"View","attributes":{"background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","tint_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {768, 960}}","nodes":[{"class":"Button","attributes":{"image_name":"ionicons-arrow-right-a-256","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","font_size":15,"title":"","enabled":true,"tint_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","flex":"","action":"play_game","font_bold":false,"name":"button1","corner_radius":0,"uuid":"74B78341-B9F6-42F4-96BB-32DDA25F8573"},"frame":"{{40, 277}, {339.5, 227.5}}","nodes":[]},{"class":"Button","attributes":{"tint_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","font_size":15,"enabled":true,"font_bold":false,"name":"button2","flex":"","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"change_character","uuid":"D1CC743E-9E48-41D4-A5C2-00EF7C4A6797","image_name":"ionicons-person-256","title":""},"frame":"{{407, 278}, {326, 226.5}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Play Game","font_name":"AvenirNext-Heavy","name":"label1","flex":"","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.306122,0.714286,0.443485,1.000000)","alignment":"center","tint_color":"RGBA(0.306122,0.714286,0.443485,1.000000)","uuid":"4011CA12-1BB9-470C-B869-16B97CFF19CB"},"frame":"{{134, 512.5}, {150, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Change Character","font_name":"AvenirNext-Heavy","name":"label2","flex":"","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.306122,0.714286,0.443485,1.000000)","alignment":"center","uuid":"46F37335-6B0A-4329-9CE7-3E4BCA414FE6"},"frame":"{{479, 512}, {181.5, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":100,"enabled":true,"text":"Cacti Killer","font_name":"AvenirNext-Heavy","name":"label3","flex":"","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","alignment":"center","uuid":"480ECFCD-00FE-4955-8D15-6DF38A6A1D56"},"frame":"{{34, 27.5}, {699, 137.5}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"By T Ferry Code","font_name":"AvenirNext-Heavy","name":"label4","flex":"","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.306122,0.714286,0.443485,1.000000)","alignment":"center","uuid":"DAC42FBB-12C0-410B-B2F5-2002B2B23612"},"frame":"{{309, 158.5}, {150, 32}}","nodes":[]},{"class":"TextField","attributes":{"tint_color":"RGBA(0.153061,0.714286,0.304592,1.000000)","font_size":17,"enabled":true,"flex":"","name":"namefield","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"center","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","placeholder":"Your Name","uuid":"9C85BC1D-94BF-4D28-A042-9FF3E9D4B5AC"},"frame":"{{283, 650.5}, {200, 32}}","nodes":[]}]}]
I print the ui files and it appears there IS more than one, even though only one is listed in my file browser.
-
Try changing the 0 to -1 in the line:
root_view = ui.load_view(find_bundled_files()[0])
so that you take the last .pyui file instead of the first .pyui file.You should also change the title of this thread to
Wrong .pyui file is getting loaded in XCode
because your problem has nothing to do with.clear_button_mode()
but is instead caused by the fact thatroot_view['namefield'] == None
. -
Will try when I get home today.
-
Tech,
Why dont you print out the name of ALL of the files that this script finds, when running on your device, not simulator. That way, you can let people know what directory things are going to, and so might not need this script anymore!You could also modify this function to look only for files that start with a specified name! the name of your pyui.
-
@ccc Just for future reference, changing the 0 to -1 in the line:
root_view = ui.load_view(find_bundled_files()[0])
worked. -
Can you please print out the full path name of ALL the files that this script finds as @JonB suggests? It would be good to understand what the paths are.
-
Using the 'find_bundled_files' as mentioned above by @techteej, I was able to compile a tentative first stand-alone App in Xcode 5.1 for iOS 7.0 - a simple App I made with my daughter, which ended up getting rejected because it didn't work on iOS 8. Now that I've upgraded to Xcode 6.1 (and iOS 8.x target devices), it seems that I am back to the issue of not being able to find supplementary files, be they .pyui files or supporting .txt files.
I've read that iOS 8 has changed the location of Documents with respect to the App directory. Has anyone figured out a way to obtain that location in a scripted way from the main Script.py?
-
Dvader, we asked tech to respond back with where files were located, so that we could document the right place for everything. So, perhaps you could try the following, and report back your results?
If you can print out the results from the following, both on the device in xcode, on the device in pythonista, and on the simulator, I think that would go a long way to figuring this out.
import os print 'user', os.path.expanduser('~') print 'cwd', os.path.abspath('.') print 'current file', os.path.abspath( __file__) print 'os file', os.path.abspath(os.__file__) print 'image file', os.path.abspath(scene.get_image_path('Test_Lenna')
The next step would be to use each of the above as starting locations for the os.walk printing out all of the pyuis we find along the way. Really, the os.walk won't be required at all, once we understand the folder structure.
-
I started to run similar print commands last night already, to try and figure this out. I'll run the exact script you mentioned and post the output tonight.
From my quick reading of the Apple documentation on file structure handling in iOS 8, they encourage/force you to query the OS when you start your App, to receive what the path to your docs is, because it doesn't seem to be the same every time. I think that's part of the changes they needed to add "app bundles". I have only started reading on this recently, so perhaps my interpretation of the documentation is wrong, so don't quote me on this.
Anyhow, will post those results. Thanks for the suggestion, @JonB.
-
in Pythonista on iPad running iOS 8.1
beginning of test printout
BASE = /private/var/mobile/Containers
user $BASE/Data/Application/number_and_letters_1
cwd $BASE/Data/Application/numbers_letters_1/Documents/
current $BASE/Data/Application/numbers_letters_1/Documents/Script.py
os file $BASE/Bundle/Application/numbers_letters_2/Pythonista.app/pylib/os.py
image file $BASE/Bundle/Application/numbers_letters_2/Pythonista.app/Textures/Test_Lenna.png
end of test printout
in IOS simulator
beginning of test printout
BASE = /Users/dvader/Library/Developer/CoreSimulator/Devices/numbers_letters_3/data/Containers
user $BASE/Data/Application/numbers_letters_4
cwd $BASE/Data/Applications/numbers_letters_4/Documents
current file $BASE/Data/Applications/numbers_letters_4>/Documents/Script.py
os file $BASE/Bundle/Application/numbers_letters_5/PythonistaProject.app/pylib/os.py
image file $BASE/Bundle/Application/numbers_letters_5/PythonistaProject.App/Textures/Test_Lenna.png
end of test printout
ad hoc build on iPad running iOS 8.1
beginning of test printout
BASE = /private/var/mobile/Containers
user $BASE/Data/Application/numbers_letters_6
cwd $BASE/Data/Application/numbers_letters_6/Documents
current $BASE/Data/Application/numbers_letters_6/Documents/Script.py
os file $BASE/Bundle/Application/numbers_letters_7/Pythonista.app/pylib/os.py
image file $BASE/Bundle/Application/numbers_letters_7/Pythonista.app/Textures/Test_Lenna.png
end of test printout
-
It does seem like expanduser and initial Script directory are in the Application Data files consistently in iOS 8, while the supporting libraries are in the Application Bundle files. I'll have to see what the implications are for the find_bundle_files function, and where to start walking through the directories.
Any other observations?
I'm now upgraded to iOS 8 and Xcode 6.1, but it would be useful to have this written down for iOS 7 as well.
-
I'd suggest setting bundle path to the user path. Have the script print out all files it finds!
There are a few more paths listed in sysconfig, though I think most of those are from compilation, but you could give those a try too.
-
Apologies for not updating this earlier.
I spent a bit of time tonight on Xcode 6.1, looking at where files are going. First, a few notes on setting up:
-
Used the latest template linked to in the forum.
-
when I open that template in Xcode 6.1, it pops up with a couple of comments on having to optimize a couple of parameters. I can't remember what those were now, but I just agreed. Didn't seem to matter that much.
-
I use the tree structure setup by @omz, i.e. the main script is directly under the project root.
-
In Finder, I make a 'script' folder in the main project directory. All of my .py and .pyui files go there.
-
In Finder, I make an 'image' folder, where I put all of my supporting images.
-
In Xcode, I make a 'Script' group (looks like a yellow folder), and add all of the files in the 'script' Finder folder to that group. Note that those groups - those seen in a yellow folder - are just a convenient way to group and organize resources.
-
In Xcode, I make a 'my_images' group - also yellow folder - and add all of the files in the 'image' Finder folder to that group. Again, just a convenient way for Xcode to organize files. This is in contrast to the BLUE 'Textures' folder, which directly links to the 'Textures' subfolder in Finder. Any file you see in Finder in that subfolder, will automatically appear in your Xcode project in the 'Textures' BLUE folder.
-
With all this being done, I open the 'AppDelegate.m' file in Xcode and add, before the '@end' line, the few lines of code posted by @omz, which address the fopen, fwrite and putenv objects. You can find those at https://omz-forums.appspot.com/pythonista/post/5862618212335616.
-
somewhere in your main script, or in supporting scripts, you'll need the find_bundled_files function described in another post.
-
If you organize your project as I describe here, all of your .pyui files will end up in the main App folder, just one branch above the os.py file as seen above, in the PythonistaProject.App folder, if you haven't changed anything further in your project. Note that all resources, .py, .pyui, custom images, text files that I've added ended up in here. The ONLY file that was in the Documents folder (os.path.join(os.path.expanduser('~'), Documents) is the main script (Script.py).
I'm sure there are other ways to organize your folders. I've started reading through some of the 'Build' scripts that the Xcode template has. This is where you see the destination of files in your App. You can try playing around with stuff there. But if you don't, I would recommend start with the find_bundled_files script to find your specific resources, and once you know where to locate them, you can hard-code the relative path, so that your App starts up faster. I'm hoping to do that as an update to the drawing App I developed with my kids ("Drawing with Sonia") and posted recently on the App Store; it does have a bit of a slower launch.
In addition to all this, a couple more comments - sorry for the very long post:
-
If you click on the Project root in Xcode and look at the General properties, I recommend switching to using Xcode assets (.xcassets) files for the app icon and launch images. They've added that functionality since Xcode 5. You just drag and drop the images in there, and it manages everything else for you.
-
In the main info.plist file, I've always had to switch the 'Application requires iPhone environment' to YES, otherwise, things don't work for me. Even though the only App I've posted is an iPad App, that flag seemed to be necessary.
-
As @omz suggested, if you don't need matplotlib, numpy, images, sounds or other resources already included, I definitely recommend removing them carefully. The base size of an App, if you just use it as is, will run over 50MB just from having to compile for the different processors as well.
-
And speaking of different processors supported: again clicking on the main Project root, and going in to the 'Build Settings', you need to remove 'arm64' from the 'Valid Architectures'. Currently, the project isn't compatible with 64-bit, but @omz recently confirmed in another post that he has that support ready for a future version, even though it does take up more space as a project.
-
Finally, I would recommend trying to figure out a good place in your App, or in the online description, to give proper credit where it's due. Whether it's recognizing all the hard work @omz has put into Pythonista, or any resources he's included in the template, or any resources you're adding yourself.
I believe these are most of the tips I can give to you. When it comes to setting up a Developer account and figuring out the iOS App development and posting pipeline, it took me a good several weeks to pass that hurdle, but it is certainly doable. I wish you good luck with that part, and look forward to seeing what can be accomplished with the Pythonista framework.
-