@@ -10,6 +10,7 @@ import Future = require("fibers/future");
10
10
import { PlistSession } from "plist-merge-patch" ;
11
11
import { EOL } from "os" ;
12
12
import * as temp from "temp" ;
13
+ import * as plist from "plist" ;
13
14
14
15
export class IOSProjectService extends projectServiceBaseLib . PlatformProjectServiceBase implements IPlatformProjectService {
15
16
private static XCODE_PROJECT_EXT_NAME = ".xcodeproj" ;
@@ -453,9 +454,93 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
453
454
} ) . future < boolean > ( ) ( ) ;
454
455
}
455
456
457
+ /**
458
+ * Patch **LaunchScreen.xib** so we can be backward compatible for eternity.
459
+ * The **xcodeproj** template proior v**2.1.0** had blank white screen launch screen.
460
+ * We extended that by adding **app/AppResources/iOS/LaunchScreen.storyboard**
461
+ * However for projects created prior **2.1.0** to keep working without the obsolete **LaunchScreen.xib**
462
+ * we must still provide it on prepare.
463
+ * Here we check if **UILaunchStoryboardName** is set to **LaunchScreen** in the **platform/ios/<proj>/<proj>-Info.plist**.
464
+ * If it is, and no **LaunchScreen.storyboard** nor **.xib** is found in the project, we will create one.
465
+ */
466
+ private provideLaunchScreenIfMissing ( ) : void {
467
+ try {
468
+ this . $logger . trace ( "Checking if we need to provide compatability LaunchScreen.xib" ) ;
469
+ let platformData = this . platformData ;
470
+ let projectPath = path . join ( platformData . projectRoot , this . $projectData . projectName ) ;
471
+ let projectPlist = this . getInfoPlistPath ( ) ;
472
+ let plistContent = plist . parse ( this . $fs . readText ( projectPlist ) . wait ( ) ) ;
473
+ let storyName = plistContent [ "UILaunchStoryboardName" ] ;
474
+ this . $logger . trace ( `Examining ${ projectPlist } UILaunchStoryboardName: "${ storyName } ".` ) ;
475
+ if ( storyName !== "LaunchScreen" ) {
476
+ this . $logger . trace ( "The project has its UILaunchStoryboardName set to " + storyName + " which is not the pre v2.1.0 default LaunchScreen, probably the project is migrated so we are good to go." ) ;
477
+ return ;
478
+ }
479
+
480
+ let expectedStoryPath = path . join ( projectPath , "Resources" , "LaunchScreen.storyboard" ) ;
481
+ if ( this . $fs . exists ( expectedStoryPath ) . wait ( ) ) {
482
+ // Found a LaunchScreen on expected path
483
+ this . $logger . trace ( "LaunchScreen.storyboard was found. Project is up to date." ) ;
484
+ return ;
485
+ }
486
+ this . $logger . trace ( "LaunchScreen file not found at: " + expectedStoryPath ) ;
487
+
488
+ let expectedXibPath = path . join ( projectPath , "en.lproj" , "LaunchScreen.xib" ) ;
489
+ if ( this . $fs . exists ( expectedXibPath ) . wait ( ) ) {
490
+ this . $logger . trace ( "Obsolete LaunchScreen.xib was found. It'k OK, we are probably running with iOS runtime from pre v2.1.0." ) ;
491
+ return ;
492
+ }
493
+ this . $logger . trace ( "LaunchScreen file not found at: " + expectedXibPath ) ;
494
+
495
+ let isTheLaunchScreenFile = ( fileName : string ) => fileName === "LaunchScreen.xib" || fileName === "LaunchScreen.storyboard" ;
496
+ let matches = this . $fs . enumerateFilesInDirectorySync ( projectPath , isTheLaunchScreenFile , { enumerateDirectories : false } ) ;
497
+ if ( matches . length > 0 ) {
498
+ this . $logger . trace ( "Found LaunchScreen by slowly traversing all files here: " + matches + "\nConsider moving the LaunchScreen so it could be found at: " + expectedStoryPath ) ;
499
+ return ;
500
+ }
501
+
502
+ let compatabilityXibPath = path . join ( projectPath , "Resources" , "LaunchScreen.xib" ) ;
503
+ this . $logger . warn ( `Failed to find LaunchScreen.storyboard but it was specified in the Info.plist.
504
+ Consider updating the resources in app/App_Resources/iOS/.
505
+ A good starting point would be to create a new project and diff the changes with your current one.
506
+ Also the following repo may be helpful: https://github.com/NativeScript/template-hello-world/tree/master/App_Resources/iOS
507
+ We will now place an empty obsolete compatability white screen LauncScreen.xib for you in ${ path . relative ( this . $projectData . projectDir , compatabilityXibPath ) } so your app may appear as it did in pre v2.1.0 versions of the ios runtime.` ) ;
508
+
509
+ let content = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
510
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
511
+ <dependencies>
512
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
513
+ </dependencies>
514
+ <objects>
515
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
516
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
517
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
518
+ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
519
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
520
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
521
+ <nil key="simulatedStatusBarMetrics"/>
522
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
523
+ <point key="canvasLocation" x="548" y="455"/>
524
+ </view>
525
+ </objects>
526
+ </document>` ;
527
+ try {
528
+ this . $fs . createDirectory ( path . dirname ( compatabilityXibPath ) ) . wait ( ) ;
529
+ this . $fs . writeFile ( compatabilityXibPath , content ) . wait ( ) ;
530
+ } catch ( e ) {
531
+ this . $logger . warn ( "We have failed to add compatability LaunchScreen.xib due to: " + e ) ;
532
+ }
533
+ } catch ( e ) {
534
+ this . $logger . warn ( "We have failed to check if we need to add a compatability LaunchScreen.xib due to: " + e ) ;
535
+ }
536
+ }
537
+
456
538
public prepareProject ( ) : IFuture < void > {
457
539
return ( ( ) => {
458
540
let project = this . createPbxProj ( ) ;
541
+
542
+ this . provideLaunchScreenIfMissing ( ) ;
543
+
459
544
let resources = project . pbxGroupByName ( "Resources" ) ;
460
545
461
546
if ( resources ) {
@@ -504,11 +589,19 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
504
589
} ) . future < void > ( ) ( ) ;
505
590
}
506
591
592
+ private getInfoPlistPath ( ) : string {
593
+ return this . $options . baseConfig ||
594
+ path . join (
595
+ this . $projectData . projectDir ,
596
+ constants . APP_FOLDER_NAME ,
597
+ constants . APP_RESOURCES_FOLDER_NAME ,
598
+ this . platformData . normalizedPlatformName ,
599
+ this . platformData . configurationFileName
600
+ ) ;
601
+ }
507
602
public ensureConfigurationFileInAppResources ( ) : IFuture < void > {
508
603
return ( ( ) => {
509
- let projectDir = this . $projectData . projectDir ;
510
- let infoPlistPath = this . $options . baseConfig || path . join ( projectDir , constants . APP_FOLDER_NAME , constants . APP_RESOURCES_FOLDER_NAME , this . platformData . normalizedPlatformName , this . platformData . configurationFileName ) ;
511
-
604
+ let infoPlistPath = this . getInfoPlistPath ( ) ;
512
605
if ( ! this . $fs . exists ( infoPlistPath ) . wait ( ) ) {
513
606
// The project is missing Info.plist, try to populate it from the project template.
514
607
let projectTemplateService : IProjectTemplatesService = this . $injector . resolve ( "projectTemplatesService" ) ;
0 commit comments