diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h index 7f0cd2f92b..6c8a0d99f7 100644 --- a/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h +++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h @@ -605,7 +605,10 @@ private: } addPlistDictionaryKey (dict, "CFBundleExecutable", "${EXECUTABLE_NAME}"); - addPlistDictionaryKey (dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String()); + + if (! iOS) // (NB: on iOS this causes error ITMS-90032 during publishing) + addPlistDictionaryKey (dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String()); + addPlistDictionaryKey (dict, "CFBundleIdentifier", project.getBundleIdentifier().toString()); addPlistDictionaryKey (dict, "CFBundleName", projectName); addPlistDictionaryKey (dict, "CFBundlePackageType", xcodePackageType); @@ -655,6 +658,9 @@ private: if (iOS) { + // Forcing full screen disables the split screen feature and prevents error ITMS-90475 + addPlistDictionaryKeyBool (dict, "UIRequiresFullScreen", true); + static const char* kDefaultiOSOrientationStrings[] = { "UIInterfaceOrientationPortrait", @@ -1342,20 +1348,7 @@ private: } } - String getiOSAssetContents (var images) const - { - DynamicObject::Ptr v (new DynamicObject()); - - var info (new DynamicObject()); - info.getDynamicObject()->setProperty ("version", 1); - info.getDynamicObject()->setProperty ("author", "xcode"); - - v->setProperty ("images", images); - v->setProperty ("info", info); - - return JSON::toString (var (v)); - } - + //============================================================================== struct AppIconType { const char* idiom; @@ -1371,7 +1364,9 @@ private: { { "iphone", "29x29", "Icon-Small.png", "1x", 29 }, { "iphone", "29x29", "Icon-Small@2x.png", "2x", 58 }, + { "iphone", "29x29", "Icon-Small@3x.png", "3x", 87 }, { "iphone", "40x40", "Icon-Spotlight-40@2x.png", "2x", 80 }, + { "iphone", "40x40", "Icon-Spotlight-40@3x.png", "3x", 120 }, { "iphone", "57x57", "Icon.png", "1x", 57 }, { "iphone", "57x57", "Icon@2x.png", "2x", 114 }, { "iphone", "60x60", "Icon-60@2x.png", "2x", 120 }, @@ -1391,10 +1386,9 @@ private: return Array (types, numElementsInArray (types)); } - String getiOSAppIconContents() const + static String getiOSAppIconContents() { - const Array types = getiOSAppIconTypes(); - + const Array types (getiOSAppIconTypes()); var images; for (int i = 0; i < types.size(); ++i) @@ -1412,46 +1406,105 @@ private: return getiOSAssetContents (images); } - String getiOSLaunchImageContents() const + //============================================================================== + struct ImageType { - struct ImageType + const char* orientation; + const char* idiom; + const char* subtype; + const char* extent; + const char* scale; + const char* filename; + const int width; + const int height; + }; + + static Array getiOSLaunchImageTypes() + { + ImageType types[] = { - const char* orientation; - const char* idiom; - const char* extent; - const char* scale; + { "portrait", "iphone", nullptr, "full-screen", "2x", "LaunchImage-iphone-2x.png", 640, 960 }, + { "portrait", "iphone", "retina4", "full-screen", "2x", "LaunchImage-iphone-retina4.png", 640, 1136 }, + { "portrait", "ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-portrait-1x.png", 768, 1024 }, + { "landscape","ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-landscape-1x.png", 1024, 768 }, + { "portrait", "ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-portrait-2x.png", 1536, 2048 }, + { "landscape","ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-landscape-2x.png", 2048, 1536 } }; - const ImageType types[] = { { "portrait", "iphone", "full-screen", "2x" }, - { "landscape", "iphone", "full-screen", "2x" }, - { "portrait", "ipad", "full-screen", "1x" }, - { "landscape", "ipad", "full-screen", "1x" }, - { "portrait", "ipad", "full-screen", "2x" }, - { "landscape", "ipad", "full-screen", "2x" } }; + return Array (types, numElementsInArray (types)); + } + + static String getiOSLaunchImageContents() + { + const Array types (getiOSLaunchImageTypes()); var images; - for (size_t i = 0; i < sizeof (types) / sizeof (types[0]); ++i) + for (int i = 0; i < types.size(); ++i) { + const ImageType& type = types.getReference(i); + DynamicObject::Ptr d = new DynamicObject(); - d->setProperty ("orientation", types[i].orientation); - d->setProperty ("idiom", types[i].idiom); - d->setProperty ("extent", types[i].extent); + d->setProperty ("orientation", type.orientation); + d->setProperty ("idiom", type.idiom); + d->setProperty ("extent", type.extent); d->setProperty ("minimum-system-version", "7.0"); - d->setProperty ("scale", types[i].scale); + d->setProperty ("scale", type.scale); + d->setProperty ("filename", type.filename); + + if (type.subtype != nullptr) + d->setProperty ("subtype", type.subtype); + images.append (var (d)); } return getiOSAssetContents (images); } + static void createiOSLaunchImageFiles (const File& launchImageSet) + { + const Array types (getiOSLaunchImageTypes()); + + for (int i = 0; i < types.size(); ++i) + { + const ImageType& type = types.getReference(i); + + Image image (Image::ARGB, type.width, type.height, true); // (empty black image) + image.clear (image.getBounds(), Colours::black); + + MemoryOutputStream pngData; + PNGImageFormat pngFormat; + pngFormat.writeImageToStream (image, pngData); + overwriteFileIfDifferentOrThrow (launchImageSet.getChildFile (type.filename), pngData); + } + } + + //============================================================================== + static String getiOSAssetContents (var images) + { + DynamicObject::Ptr v (new DynamicObject()); + + var info (new DynamicObject()); + info.getDynamicObject()->setProperty ("version", 1); + info.getDynamicObject()->setProperty ("author", "xcode"); + + v->setProperty ("images", images); + v->setProperty ("info", info); + + return JSON::toString (var (v)); + } + void createiOSAssetsFolder() const { - File assets (getTargetFolder().getChildFile (project.getProjectFilenameRoot()).getChildFile ("Images.xcassets")); + const File assets (getTargetFolder().getChildFile (project.getProjectFilenameRoot()) + .getChildFile ("Images.xcassets")); + const File iconSet (assets.getChildFile ("AppIcon.appiconset")); + const File launchImage (assets.getChildFile ("LaunchImage.launchimage")); - overwriteFileIfDifferentOrThrow (assets.getChildFile ("AppIcon.appiconset").getChildFile ("Contents.json"), getiOSAppIconContents()); - createiOSIconFiles (assets.getChildFile ("AppIcon.appiconset")); + overwriteFileIfDifferentOrThrow (iconSet.getChildFile ("Contents.json"), getiOSAppIconContents()); + createiOSIconFiles (iconSet); - overwriteFileIfDifferentOrThrow (assets.getChildFile ("LaunchImage.launchimage").getChildFile ("Contents.json"), getiOSLaunchImageContents()); + overwriteFileIfDifferentOrThrow (launchImage.getChildFile ("Contents.json"), getiOSLaunchImageContents()); + createiOSLaunchImageFiles (launchImage); RelativePath assetsPath (assets, getTargetFolder(), RelativePath::buildTargetFolder); addFileReference (assetsPath.toUnixStyle());