Skip to content

Commit 0ddab0a

Browse files
authored
docs: Add upgrade guide for plugin authors for 8.x (#1498)
1 parent 8eacc92 commit 0ddab0a

File tree

4 files changed

+305
-2
lines changed

4 files changed

+305
-2
lines changed

CordovaLib/CordovaLib.docc/CordovaLib.md

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ For more information about Apache Cordova, visit [https://cordova.apache.org](ht
5656
- ``CDVConfigParser``
5757
- ``CDVTimer``
5858

59+
### Upgrade Guides
60+
- <doc:upgrading-8>
61+
5962
### Deprecated
6063

6164
- ``IsAtLeastiOSVersion``
+300
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
# Upgrading Plugins to Cordova iOS 8.x
2+
<!--
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one
5+
# or more contributor license agreements. See the NOTICE file
6+
# distributed with this work for additional information
7+
# regarding copyright ownership. The ASF licenses this file
8+
# to you under the Apache License, Version 2.0 (the
9+
# "License"); you may not use this file except in compliance
10+
# with the License. You may obtain a copy of the License at
11+
#
12+
# http://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing,
15+
# software distributed under the License is distributed on an
16+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
# KIND, either express or implied. See the License for the
18+
# specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
-->
22+
23+
A guide for plugin authors to understand the API changes in Cordova iOS 8.
24+
25+
Cordova iOS 8 introduces some significant changes to the exposed API for plugin authors and framework consumers. Many of these changes have been made to better align the framework with modern iOS development practices, such as adopting the `UIScene` APIs and fixing conflicts with SwiftUI projects, as well as work to improve the API experience for apps that consume Cordova as a framework (sometimes called the "platform centric workflow"). In all cases, great care has been taken to try to minimize the risk of breakage to existing 3rd party plugins.
26+
27+
Many plugins will notice new deprecation warnings when built against Cordova iOS 8, rather than outright breaking changes. This document aims to explain the changes, the rationale behind the changes, and offer sample code for plugin authors to ensure their plugin code is compatible with future versions of Cordova iOS.
28+
29+
In cases where different behavior is required for different Cordova versions, the ``CORDOVA_VERSION_MIN_REQUIRED`` macro can be used in Objective-C code to test the current Cordova version:
30+
31+
```objc
32+
#if defined(__CORDOVA_8_0_0) && CORDOVA_VERSION_MIN_REQUIRED >= __CORDOVA_8_0_0
33+
// Code for Cordova iOS 8 goes here
34+
#else
35+
// Code for older versions goes here
36+
#endif
37+
```
38+
39+
## Major Breaking Changes
40+
### Minimum iOS version update
41+
The Cordova iOS framework has increased the minimum supported iOS version from 11.0 to 13.0.
42+
43+
The minimum supported Xcode version for the Cordova tooling and generated template app is now Xcode 15.
44+
45+
### Change to the generated app project naming
46+
47+
The generated app template is now consistently named "App", including "App.xcodeproj", and "App.xcworkspace". The Xcode build target for the app is also named "App". If you are expecting the name of the Xcode project or target to match the name specified in config.xml, it will now fail to find the project.
48+
49+
Use the cordova-ios nodeJS API to retrieve the Xcode project path and other project details:
50+
51+
```js
52+
// Old code
53+
const projectRoot = context.opts.projectRoot;
54+
const platformPath = path.join(projectRoot, 'platforms', 'ios');
55+
56+
const config = getConfigParser(context, path.join(projectRoot, 'config.xml'));
57+
const projectName = config.name();
58+
59+
const pbxprojPath = path.join(platformPath, `${projectName}.xcodeproj`, 'project.pbxproj');
60+
const xcodeProject = xcode.project(pbxprojPath);
61+
```
62+
63+
```js
64+
// New code
65+
const projectRoot = context.opts.projectRoot;
66+
const platformPath = path.join(projectRoot, 'platforms', 'ios');
67+
68+
const cordova_ios = require('cordova-ios');
69+
const iosProject = new cordova_ios('ios', platformPath);
70+
71+
const xcodeProject = xcode.project(iosProject.locations.pbxproj);
72+
```
73+
74+
This updated pattern is backwards compatible with existing versions of Cordova iOS 5.0.0 and newer.
75+
76+
Moving to a consistent name for the Xcode project and target resolves a number of issues around dynamic file lookups, Xcode projects with multiple targets, and Unicode compatibility with other tools such as CocoaPods that have issues with non-ASCII project names. Beyond fixing those issues, it was never actually safe to use the `name` from config.xml directly, because even in previous versions of Cordova iOS the project name could be normalized to remove Unicode characters.
77+
78+
Using the cordova-ios JavaScript API ensures that plugins and the Cordova tooling treat projects the same way. The `locations` object contains properties for several useful paths:
79+
80+
* `root` - The platform root directory
81+
* `www` - The platform's generated web content folder
82+
* `pbxproj` - The Xcode project file (the project.pbxproj file)
83+
* `xcodeProjDir` - The Xcode project path (the .xcodeproj directory)
84+
* `xcodeCordovaProj` - The platform folder containing the Cordova iOS app code
85+
86+
You can find the app's Info.plist file in a backwards-compatible way by doing something like this:
87+
88+
```javascript
89+
const projName = path.basename(iosProject.locations.xcodeCordovaProj);
90+
const infoPlistPath = path.join(iosProject.locations.xcodeCordovaProj, `${projName}-Info.plist`);
91+
```
92+
93+
### CDVAppDelegate window deprecation
94+
95+
The generated app template now uses the iOS scene API (using `UISceneDelegate`) to support multiple windows, which means that it's no longer a safe assumption that an app has only a single window.
96+
97+
The ``CDVAppDelegate/window`` property of ``CDVAppDelegate`` is deprecated as a result. This property will always have a `nil` value.
98+
99+
In a plugin class, you should retrieve the `UIWindow` for the current view controller:
100+
101+
```objc
102+
// Old code
103+
CDVAppDelegate *delegate = (CDVAppDelegate *)[[UIApplication sharedApplication] delegate];
104+
UIWindow *currentWindow = delegate.window;
105+
```
106+
107+
```objc
108+
// New code
109+
UIWindow *currentWindow = self.viewController.view.window;
110+
```
111+
112+
There may be other cases where things that previously assumed a single window (such as `UIScreen` bounds) require updating to support iOS scenes.
113+
114+
### CDVAppDelegate viewController deprecation
115+
116+
The ``CDVAppDelegate/viewController`` property of ``CDVAppDelegate`` is deprecated, and may return `nil` if a `CDVViewController` has not yet been initialized.
117+
118+
Plugins should prefer accessing the view controller using their ``CDVPlugin/viewController`` property (which is now typed as ``CDVViewController``).
119+
120+
### UIView scrollView property deprecation
121+
122+
The `scrollView` property added as a global category extension to `UIView` is now deprecated in Objective C code and **removed entirely in Swift code**. This is to prevent conflicts with other Swift classes that extend `UIView` and have their own `scrollView` properties.
123+
124+
You can still access the `scrollView` property of the web view by dynamically invoking the method:
125+
126+
```objc
127+
// Old code
128+
UIScrollView *scroller = self.webView.scrollView;
129+
```
130+
131+
```objc
132+
// New code (Objective-C)
133+
#import <objc/message.h>
134+
135+
UIScrollView *scroller;
136+
SEL scrollViewSelector = NSSelectorFromString(@"scrollView");
137+
138+
if ([self.webView respondsToSelector:scrollViewSelector]) {
139+
scroller = ((id (*)(id, SEL))objc_msgSend)(self.webView, scrollViewSelector);
140+
}
141+
```
142+
143+
```swift
144+
// New code (Swift)
145+
var scroller : UIScrollView?
146+
let scrollViewSelector = NSSelectorFromString("scrollView")
147+
148+
if webView.responds(to: scrollViewSelector) {
149+
scroller = webView.perform(scrollViewSelector)?.takeUnretainedValue() as? UIScrollView
150+
}
151+
```
152+
153+
This updated code is compatible with existing versions of Cordova iOS.
154+
155+
## Other Major Changes
156+
### Deprecating AppDelegate category extensions
157+
158+
Please extend the ``CDVAppDelegate`` base class instead:
159+
160+
```objc
161+
// Old code
162+
#import "AppDelegate.h"
163+
164+
@interface AppDelegate (myplugin)
165+
// Added extension methods here
166+
@end
167+
```
168+
169+
```objc
170+
// New code
171+
#import <Cordova/CDVAppDelegate.h>
172+
173+
@interface CDVAppDelegate (myplugin)
174+
// Added extension methods here
175+
@end
176+
```
177+
178+
It was never a completely safe assumption that an app using Cordova would include a class named `AppDelegate` that was a subclass of `CDVAppDelegate` due to the ability to embed CordovaLib in an existing iOS app project as a library. If your plugin needs to add behaviour to the app delegate, it should do so to the ``CDVAppDelegate`` base class.
179+
180+
The updated code is backwards compatible with several existing Cordova iOS versions.
181+
182+
### Deprecating MainViewController category extensions
183+
184+
Please extend the ``CDVViewController`` base class instead:
185+
186+
```objc
187+
// Old code
188+
#import "MainViewController.h"
189+
190+
@interface MainViewController (myplugin)
191+
// Added extension methods here
192+
@end
193+
```
194+
195+
```objc
196+
// New code
197+
#import <Cordova/CDVViewController.h>
198+
199+
@interface CDVViewController (myplugin)
200+
// Added extension methods here
201+
@end
202+
```
203+
204+
It was never a completely safe assumption that an app using Cordova would include a class named `MainViewController` that was a subclass of `CDVViewController` due to the ability to embed CordovaLib in an existing iOS app project as a library. If your plugin needs to add behaviour to the Cordova view controller, it should do so to the ``CDVViewController`` base class.
205+
206+
This updated code is backwards compatible with several existing Cordova iOS versions.
207+
208+
### Deprecating CDVCommandStatus constants in Swift
209+
210+
For plugins written in Swift, the old `CDVCommandStatus_*` constants are deprecated in favour of the enum based aliases:
211+
212+
```swift
213+
// Old code
214+
self.commandDelegate.send(CDVPluginResult(status: CDVCommandStatus_OK), callbackId: command.callbackId);
215+
```
216+
217+
```swift
218+
// New code
219+
self.commandDelegate.send(CDVPluginResult(status: .ok), callbackId: command.callbackId);
220+
```
221+
222+
These aliases were introduced in and are backwards compatible with all existing versions since Cordova iOS 5.0.0. See ``CDVCommandStatus`` for a list of the enum values.
223+
224+
## Public API Removals
225+
The following classes were previously exposed as part of the Cordova iOS public API, but were only used as internal implementation details. To better establish the public/private API boundary within Cordova iOS, they have been removed from the public API in Cordova iOS 8.
226+
227+
* `CDVAllowList`
228+
* `CDVURLSchemeHandler`
229+
230+
The following headers are deprecated due to adding global category extensions to system classes and will be removed in a future version of Cordova iOS:
231+
232+
* `<Cordova/NSDictionary+CordovaPreferences.h>`
233+
Use the new ``CDVSettingsDictionary`` class, which provides all the same methods.
234+
235+
* `<Cordova/NSMutableArray+QueueAdditions.h>`
236+
This was only ever intended as an internal implementation detail.
237+
238+
* `<Cordova/CDV.h>`
239+
Use `<Cordova/Cordova.h>` instead.
240+
241+
## Other Changes
242+
* ``CDVCommandDelegate``
243+
* The ``CDVCommandDelegate/urlTransformer`` property is deprecated.
244+
This property was never used, and does not need to be a required part of the protocol.
245+
246+
* The ``CDVCommandDelegate/settings`` property is now typed as ``CDVSettingsDictionary``.
247+
248+
* ``CDVConfigParser``
249+
* Added a ``CDVConfigParser/parseConfigFile:`` class method.
250+
251+
* Added a ``CDVConfigParser/parseConfigFile:withDelegate:`` class method.
252+
253+
* ``CDVPlugin``
254+
* The ``CDVPlugin/viewController`` property is now typed as ``CDVViewController``.
255+
Previously this was typed as the more generic `UIViewController`.
256+
257+
* Plugin classes that intend to override WebKit scheme handling should implement the ``CDVPluginSchemeHandler`` protocol to ensure compliance with the required methods.
258+
259+
* The ``CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification`` notification is now deprecated.
260+
The existing ``CDVPluginHandleOpenURLNotification`` notification now includes the source and annotation in its `userInfo` dictionary.
261+
262+
* ``CDVPluginSchemeHandler``
263+
* Newly added protocol for plugins wishing to override WebKit scheme handling for web requests.
264+
265+
* ``CDVScreenOrientationDelegate``
266+
* This protocol is now deprecated and no longer used.
267+
268+
* ``CDVSettingsDictionary``
269+
* Newly added class to provide `NSDictionary`-like access to config.xml preferences, without relying on global category extensions to `NSDictionary`.
270+
271+
* ``CDVViewController``
272+
* The ``CDVViewController/settings`` property is now typed as ``CDVSettingsDictionary``.
273+
274+
* The ``CDVViewController/wwwFolderName`` property is deprecated.
275+
This property has been renamed to ``CDVViewController/webContentFolderName``.
276+
277+
* The ``CDVViewController/appURLScheme`` property is deprecated.
278+
This property was not used internally by Cordova iOS and should not be used by plugins.
279+
280+
* The ``CDVViewController/pluginsMap`` and ``CDVViewController/pluginObjects`` properties are deprecated.
281+
These were internal implementation details that should not have been exposed.
282+
283+
* Added an ``CDVViewController/enumerablePlugins`` property that can safely be iterated to loop over all loaded plugins.
284+
285+
* The ``CDVViewController/configParser`` property is deprecated due to not being used.
286+
287+
* The ``CDVViewController/parseSettingsWithParser:`` method is deprecated.
288+
Use the ``CDVConfigParser/parseConfigFile:withDelegate:`` class method on ``CDVConfigParser`` instead.
289+
290+
* Added a new ``CDVViewController/showInitialSplashScreen`` property.
291+
This property is inspectable in Interface Builder for embedding apps to indicate if the splash screen should be displayed during web content loading.
292+
293+
* Added a new ``CDVViewController/backgroundColor`` property.
294+
This property is inspectable in Interface Builder for embedding apps to set the view controller background color.
295+
296+
* Added a new ``CDVViewController/splashBackgroundColor`` property.
297+
This property is inspectable in Interface Builder for embedding apps to set the splash screen background color.
298+
299+
* The ``CDVViewController/showLaunchScreen:`` method is deprecated.
300+
This method has been renamed to ``CDVViewController/showSplashScreen:``.

CordovaLib/include/Cordova/CDVAppDelegate.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
3434
behavior to the app by building on system events such as URL handling, push
3535
notification registration, and deep linking.
3636
37-
See ``UIApplicationDelegate`` for more details about app delegates.
37+
See `UIApplicationDelegate` for more details about app delegates.
3838
*/
3939
@interface CDVAppDelegate : UIResponder <UIApplicationDelegate>
4040

CordovaLib/include/Cordova/CDVConfigParser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
3131
Use ``parseConfigFile:`` to load data from a file path.
3232
3333
Use ``parseConfigFile:withDelegate:`` if you need to intercept the XML parsing
34-
and handle the data yourself with an ``NSXMLParserDelegate``.
34+
and handle the data yourself with an `NSXMLParserDelegate`.
3535
*/
3636
@interface CDVConfigParser : NSObject <NSXMLParserDelegate>
3737

0 commit comments

Comments
 (0)