summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2017-01-26 16:05:42 -0500
committerGitHub <noreply@github.com>2017-01-26 16:05:42 -0500
commita3eef8de162910a0c02a9a005b692c4172a153b1 (patch)
tree5cca3f70502b8ffb24edd66ddabdb0c153bbeb05
parent21cc10ffeed809384bb6aa8f88f3e7d20b7dcc4e (diff)
parentb7ee68bfebc6ce528195883d2fd94820cd32ee62 (diff)
downloadsdl_ios-a3eef8de162910a0c02a9a005b692c4172a153b1.tar.gz
Merge pull request #510 from smartdevicelink/hotfix/issue_509_stop_proxy
Updated `stop` method of SDLManager to actually stop.
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj2
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.h6
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m104
-rw-r--r--SmartDeviceLink/SDLManager.h2
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m31
-rw-r--r--SmartDeviceLink_Example/Base.lproj/ConnectionIAPTableViewController.storyboard27
-rw-r--r--SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard40
-rw-r--r--SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m10
-rw-r--r--SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m6
-rw-r--r--SmartDeviceLink_Example/Classes/ProxyManager.m13
10 files changed, 150 insertions, 91 deletions
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
index ba0d62d08..d131e4d29 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -5167,6 +5167,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -5180,6 +5181,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
diff --git a/SmartDeviceLink/SDLLifecycleManager.h b/SmartDeviceLink/SDLLifecycleManager.h
index 54c584c7b..9332d5d9d 100644
--- a/SmartDeviceLink/SDLLifecycleManager.h
+++ b/SmartDeviceLink/SDLLifecycleManager.h
@@ -36,8 +36,10 @@
NS_ASSUME_NONNULL_BEGIN
typedef NSString SDLLifecycleState;
-extern SDLLifecycleState *const SDLLifecycleStateDisconnected;
-extern SDLLifecycleState *const SDLLifecycleStateTransportConnected;
+extern SDLLifecycleState *const SDLLifecycleStateStopped;
+extern SDLLifecycleState *const SDLLifecycleStateStarted;
+extern SDLLifecycleState *const SDLLifecycleStateReconnecting;
+extern SDLLifecycleState *const SDLLifecycleStateConnected;
extern SDLLifecycleState *const SDLLifecycleStateRegistered;
extern SDLLifecycleState *const SDLLifecycleStateSettingUpManagers;
extern SDLLifecycleState *const SDLLifecycleStatePostManagerProcessing;
diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m
index 8f205afd4..e322452f3 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -43,8 +43,10 @@
NS_ASSUME_NONNULL_BEGIN
-SDLLifecycleState *const SDLLifecycleStateDisconnected = @"TransportDisconnected";
-SDLLifecycleState *const SDLLifecycleStateTransportConnected = @"TransportConnected";
+SDLLifecycleState *const SDLLifecycleStateStopped = @"Stopped";
+SDLLifecycleState *const SDLLifecycleStateStarted = @"Started";
+SDLLifecycleState *const SDLLifecycleStateReconnecting = @"Reconnecting";
+SDLLifecycleState *const SDLLifecycleStateConnected = @"Connected";
SDLLifecycleState *const SDLLifecycleStateRegistered = @"Registered";
SDLLifecycleState *const SDLLifecycleStateSettingUpManagers = @"SettingUpManagers";
SDLLifecycleState *const SDLLifecycleStatePostManagerProcessing = @"PostManagerProcessing";
@@ -86,7 +88,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
_delegate = delegate;
// Private properties
- _lifecycleStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLLifecycleStateDisconnected states:[self.class sdl_stateTransitionDictionary]];
+ _lifecycleStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLLifecycleStateStopped states:[self.class sdl_stateTransitionDictionary]];
_lastCorrelationId = 0;
_notificationDispatcher = [[SDLNotificationDispatcher alloc] init];
_responseDispatcher = [[SDLResponseDispatcher alloc] initWithNotificationDispatcher:_notificationDispatcher];
@@ -108,25 +110,14 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
- (void)startWithReadyHandler:(SDLManagerReadyBlock)readyHandler {
self.readyHandler = [readyHandler copy];
- // Set up our logging capabilities based on the config
- [self.class sdl_updateLoggingWithFlags:self.configuration.lifecycleConfig.logFlags];
-
-// Start up the internal proxy object
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (self.configuration.lifecycleConfig.tcpDebugMode) {
- self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher tcpIPAddress:self.configuration.lifecycleConfig.tcpDebugIPAddress tcpPort:[@(self.configuration.lifecycleConfig.tcpDebugPort) stringValue]];
- } else {
- self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher];
- }
-#pragma clang diagnostic pop
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateStarted];
}
- (void)stop {
if ([self.lifecycleStateMachine isCurrentState:SDLLifecycleStateReady]) {
[self.lifecycleStateMachine transitionToState:SDLLifecycleStateUnregistering];
} else {
- [self.lifecycleStateMachine transitionToState:SDLLifecycleStateDisconnected];
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
}
}
@@ -146,17 +137,42 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
+ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_stateTransitionDictionary {
return @{
- SDLLifecycleStateDisconnected: @[SDLLifecycleStateTransportConnected],
- SDLLifecycleStateTransportConnected: @[SDLLifecycleStateDisconnected, SDLLifecycleStateRegistered],
- SDLLifecycleStateRegistered: @[SDLLifecycleStateDisconnected, SDLLifecycleStateSettingUpManagers],
- SDLLifecycleStateSettingUpManagers: @[SDLLifecycleStateDisconnected, SDLLifecycleStatePostManagerProcessing],
- SDLLifecycleStatePostManagerProcessing: @[SDLLifecycleStateDisconnected, SDLLifecycleStateReady],
- SDLLifecycleStateUnregistering: @[SDLLifecycleStateDisconnected],
- SDLLifecycleStateReady: @[SDLLifecycleStateUnregistering, SDLLifecycleStateDisconnected]
+ SDLLifecycleStateStopped: @[SDLLifecycleStateStarted],
+ SDLLifecycleStateStarted : @[SDLLifecycleStateConnected, SDLLifecycleStateStopped, SDLLifecycleStateReconnecting],
+ SDLLifecycleStateReconnecting: @[SDLLifecycleStateStarted],
+ SDLLifecycleStateConnected: @[SDLLifecycleStateStopped, SDLLifecycleStateReconnecting, SDLLifecycleStateRegistered],
+ SDLLifecycleStateRegistered: @[SDLLifecycleStateStopped, SDLLifecycleStateReconnecting, SDLLifecycleStateSettingUpManagers],
+ SDLLifecycleStateSettingUpManagers: @[SDLLifecycleStateStopped, SDLLifecycleStateReconnecting, SDLLifecycleStatePostManagerProcessing],
+ SDLLifecycleStatePostManagerProcessing: @[SDLLifecycleStateStopped, SDLLifecycleStateReconnecting, SDLLifecycleStateReady],
+ SDLLifecycleStateUnregistering: @[SDLLifecycleStateStopped],
+ SDLLifecycleStateReady: @[SDLLifecycleStateUnregistering, SDLLifecycleStateStopped, SDLLifecycleStateReconnecting]
};
}
-- (void)didEnterStateTransportDisconnected {
+- (void)didEnterStateStarted {
+ // Set up our logging capabilities based on the config
+ [self.class sdl_updateLoggingWithFlags:self.configuration.lifecycleConfig.logFlags];
+
+ // Start up the internal proxy object
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ if (self.configuration.lifecycleConfig.tcpDebugMode) {
+ self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher tcpIPAddress:self.configuration.lifecycleConfig.tcpDebugIPAddress tcpPort:[@(self.configuration.lifecycleConfig.tcpDebugPort) stringValue]];
+ } else {
+ self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher];
+ }
+#pragma clang diagnostic pop
+}
+
+- (void)didEnterStateStopped {
+ [self sdl_stopManager:NO];
+}
+
+- (void)didEnterStateReconnecting {
+ [self sdl_stopManager:YES];
+}
+
+- (void)sdl_stopManager:(BOOL)shouldRestart {
[self.fileManager stop];
[self.permissionManager stop];
[self.lockScreenManager stop];
@@ -167,12 +183,20 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
self.hmiLevel = nil;
[self sdl_disposeProxy]; // call this method instead of stopProxy to avoid double-dispatching
- [self.delegate managerDidDisconnect];
- [self startWithReadyHandler:self.readyHandler]; // Start up again to start watching for new connections
+ // Due to a race condition internally with EAStream, we cannot immediately attempt to restart the proxy, as we will randomly crash.
+ // Apple Bug ID #30059457
+ __weak typeof(self) weakSelf = self;
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ [weakSelf.delegate managerDidDisconnect];
+
+ if (shouldRestart) {
+ [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateStarted];
+ }
+ });
}
-- (void)didEnterStateTransportConnected {
+- (void)didEnterStateConnected {
// If we have security managers, add them to the proxy
if (self.configuration.lifecycleConfig.securityManagers != nil) {
[self.proxy addSecurityManagers:self.configuration.lifecycleConfig.securityManagers forAppId:self.configuration.lifecycleConfig.appId];
@@ -189,7 +213,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
if (error != nil || ![response.success boolValue]) {
[SDLDebugTool logFormat:@"Failed to register the app. Error: %@, Response: %@", error, response];
weakSelf.readyHandler(NO, error);
- [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateDisconnected];
+ [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
return;
}
@@ -273,7 +297,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
[SDLDebugTool logFormat:@"SDL Error unregistering, we are going to hard disconnect: %@, response: %@", error, response];
}
- [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateDisconnected];
+ [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
}];
}
@@ -341,7 +365,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
}
- (void)sdl_sendRequest:(SDLRPCRequest *)request withResponseHandler:(nullable SDLResponseHandler)handler {
- // We will allow things to be sent in a "SDLLifeCycleStateTransportConnected" state in the private method, but block it in the public method sendRequest:withCompletionHandler: so that the lifecycle manager can complete its setup without being bothered by developer error
+ // We will allow things to be sent in a "SDLLifeCycleStateConnected" state in the private method, but block it in the public method sendRequest:withCompletionHandler: so that the lifecycle manager can complete its setup without being bothered by developer error
NSParameterAssert(request != nil);
@@ -378,7 +402,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
return @(++self.lastCorrelationId);
}
-+ (BOOL)sdl_checkNotification:(NSNotification *)notification containsKindOfClass:(Class) class {
++ (BOOL)sdl_checkNotification:(NSNotification *)notification containsKindOfClass:(Class)class {
NSAssert([notification.userInfo[SDLNotificationUserInfoObject] isKindOfClass:class], @"A notification was sent with an unanticipated object");
if (![notification.userInfo[SDLNotificationUserInfoObject] isKindOfClass:class]) {
return NO;
@@ -387,7 +411,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
return YES;
}
- + (void)sdl_updateLoggingWithFlags : (SDLLogOutput)logFlags {
++ (void)sdl_updateLoggingWithFlags:(SDLLogOutput)logFlags {
[SDLDebugTool disable];
if ((logFlags & SDLLogOutputConsole) == SDLLogOutputConsole) {
@@ -414,11 +438,15 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
#pragma mark SDL notification observers
- (void)transportDidConnect {
- [self.lifecycleStateMachine transitionToState:SDLLifecycleStateTransportConnected];
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateConnected];
}
- (void)transportDidDisconnect {
- [self.lifecycleStateMachine transitionToState:SDLLifecycleStateDisconnected];
+ if (self.lifecycleState == SDLLifecycleStateUnregistering || self.lifecycleState == SDLLifecycleStateStopped) {
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
+ } else {
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateReconnecting];
+ }
}
- (void)hmiStatusDidChange:(SDLRPCNotificationNotification *)notification {
@@ -445,7 +473,13 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
SDLOnAppInterfaceUnregistered *appUnregisteredNotification = notification.notification;
[SDLDebugTool logFormat:@"Remote Device forced unregistration for reason: %@", appUnregisteredNotification.reason];
- [self.lifecycleStateMachine transitionToState:SDLLifecycleStateDisconnected];
+ if ([self.lifecycleStateMachine isCurrentState:SDLLifecycleStateUnregistering]) {
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
+ } else if ([self.lifecycleStateMachine isCurrentState:SDLLifecycleStateStopped]) {
+ return;
+ } else {
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateReconnecting];
+ }
}
@end
diff --git a/SmartDeviceLink/SDLManager.h b/SmartDeviceLink/SDLManager.h
index eb10f88d3..8aa96d9f2 100644
--- a/SmartDeviceLink/SDLManager.h
+++ b/SmartDeviceLink/SDLManager.h
@@ -93,6 +93,8 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error);
/**
* Stop the manager, it will disconnect if needed and no longer look for a connection. You probably don't need to call this method ever.
+ *
+ * If you do call this method, you must wait for SDLManagerDelegate's managerDidDisconnect callback to call startWithReadyHandler:.
*/
- (void)stop;
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
index ba680de00..eb685441e 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
@@ -83,7 +83,7 @@ describe(@"a lifecycle manager", ^{
it(@"should initialize properties", ^{
expect(testManager.configuration).to(equal(testConfig));
expect(testManager.delegate).to(equal(managerDelegateMock)); // TODO: Broken on OCMock 3.3.1 & Swift 3 Quick / Nimble
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped));
expect(@(testManager.lastCorrelationId)).to(equal(@0));
expect(testManager.fileManager).toNot(beNil());
expect(testManager.permissionManager).toNot(beNil());
@@ -152,7 +152,8 @@ describe(@"a lifecycle manager", ^{
});
it(@"should do nothing", ^{
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped));
+ expect(testManager.lifecycleState).toEventuallyNot(match(SDLLifecycleStateStarted));
});
});
@@ -172,7 +173,7 @@ describe(@"a lifecycle manager", ^{
it(@"should initialize the proxy property", ^{
expect(testManager.proxy).toNot(beNil());
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStarted));
});
describe(@"after receiving a connect notification", ^{
@@ -186,7 +187,7 @@ describe(@"a lifecycle manager", ^{
it(@"should send a register app interface request and be in the connected state", ^{
OCMVerifyAllWithDelay(proxyMock, 0.5);
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateTransportConnected));
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateConnected));
});
itBehavesLike(@"unable to send an RPC", ^{ return @{ @"manager": testManager }; });
@@ -197,8 +198,8 @@ describe(@"a lifecycle manager", ^{
[NSThread sleepForTimeInterval:0.1];
});
- it(@"should be in the disconnect state", ^{
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ it(@"should be in the started state", ^{
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStarted));
});
});
@@ -207,15 +208,15 @@ describe(@"a lifecycle manager", ^{
[testManager stop];
});
- it(@"should simply disconnect", ^{
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ it(@"should simply stop", ^{
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped));
});
});
});
describe(@"in the connected state", ^{
beforeEach(^{
- [testManager.lifecycleStateMachine setToState:SDLLifecycleStateTransportConnected fromOldState:nil callEnterTransition:NO];
+ [testManager.lifecycleStateMachine setToState:SDLLifecycleStateConnected fromOldState:nil callEnterTransition:NO];
});
describe(@"after receiving a register app interface response", ^{
@@ -247,8 +248,8 @@ describe(@"a lifecycle manager", ^{
[testManager.notificationDispatcher postNotificationName:SDLTransportDidDisconnect infoObject:nil];
});
- it(@"should enter the disconnect state", ^{
- expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateDisconnected));
+ it(@"should enter the started state", ^{
+ expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateStarted));
});
});
@@ -257,8 +258,8 @@ describe(@"a lifecycle manager", ^{
[testManager stop];
});
- it(@"should enter the disconnect state", ^{
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateDisconnected));
+ it(@"should enter the stopped state", ^{
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped));
});
});
});
@@ -333,8 +334,8 @@ describe(@"a lifecycle manager", ^{
[testManager.notificationDispatcher postRPCResponseNotification:SDLDidReceiveUnregisterAppInterfaceResponse response:testUnregisterResponse];
});
- it(@"should disconnect", ^{
- expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateDisconnected));
+ it(@"should stop", ^{
+ expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateStopped));
});
});
});
diff --git a/SmartDeviceLink_Example/Base.lproj/ConnectionIAPTableViewController.storyboard b/SmartDeviceLink_Example/Base.lproj/ConnectionIAPTableViewController.storyboard
index 335364997..d8a88f6de 100644
--- a/SmartDeviceLink_Example/Base.lproj/ConnectionIAPTableViewController.storyboard
+++ b/SmartDeviceLink_Example/Base.lproj/ConnectionIAPTableViewController.storyboard
@@ -1,8 +1,13 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="J12-ul-Tx1">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="J12-ul-Tx1">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--ConnectionIAP Table View Controller-->
@@ -10,22 +15,24 @@
<objects>
<tableViewController id="J12-ul-Tx1" customClass="ConnectionIAPTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="MzB-GZ-Ook">
- <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<sections>
<tableViewSection id="Qz3-D9-j37">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="2sd-U1-9xV">
+ <rect key="frame" x="0.0" y="35" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2sd-U1-9xV" id="EhZ-2E-WQ5">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rjq-vZ-OjB">
- <rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rjq-vZ-OjB">
+ <rect key="frame" x="8" y="0.0" width="359" height="44"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<state key="normal" title="Connect">
- <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+ <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="connectButtonWasPressed:" destination="J12-ul-Tx1" eventType="touchUpInside" id="95T-fc-kXs"/>
@@ -35,8 +42,8 @@
<constraints>
<constraint firstItem="rjq-vZ-OjB" firstAttribute="top" secondItem="EhZ-2E-WQ5" secondAttribute="top" id="8GY-v0-41a"/>
<constraint firstAttribute="bottom" secondItem="rjq-vZ-OjB" secondAttribute="bottom" id="FKB-JG-o5G"/>
- <constraint firstAttribute="trailingMargin" secondItem="rjq-vZ-OjB" secondAttribute="trailing" constant="-8" id="ISQ-6b-S34"/>
- <constraint firstItem="rjq-vZ-OjB" firstAttribute="leading" secondItem="EhZ-2E-WQ5" secondAttribute="leadingMargin" constant="-8" id="PiJ-h3-NOR"/>
+ <constraint firstAttribute="trailingMargin" secondItem="rjq-vZ-OjB" secondAttribute="trailing" id="ISQ-6b-S34"/>
+ <constraint firstItem="rjq-vZ-OjB" firstAttribute="leading" secondItem="EhZ-2E-WQ5" secondAttribute="leadingMargin" id="PiJ-h3-NOR"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
diff --git a/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard b/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
index 231cff68b..63324d6de 100644
--- a/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
+++ b/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
@@ -1,31 +1,35 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="l5Q-ZP-1BO">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--ConnectionTCP Table View Controller-->
<scene sceneID="geJ-kX-PTm">
<objects>
<tableViewController id="l5Q-ZP-1BO" customClass="ConnectionTCPTableViewController" sceneMemberID="viewController">
- <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" showsSelectionImmediatelyOnTouchBegin="NO" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="7ZH-AV-Zyf">
- <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="7ZH-AV-Zyf">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<sections>
<tableViewSection headerTitle="TCP Server" id="bF6-yi-Ial">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="pbJ-oz-jNt">
- <rect key="frame" x="0.0" y="50" width="600" height="44"/>
+ <rect key="frame" x="0.0" y="56" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pbJ-oz-jNt" id="B7X-yY-lwJ">
- <rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="IP Address" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="xqM-s4-9RV">
- <rect key="frame" x="8" y="0.0" width="584" height="44"/>
+ <rect key="frame" x="8" y="0.0" width="359" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="5Pw-mh-x83"/>
</constraints>
@@ -41,14 +45,14 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="C5b-fS-v3d">
- <rect key="frame" x="0.0" y="94" width="600" height="44"/>
+ <rect key="frame" x="0.0" y="100" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="C5b-fS-v3d" id="ZD4-xA-og5">
- <rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Port" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hsI-ld-8xY">
- <rect key="frame" x="8" y="0.0" width="584" height="44"/>
+ <rect key="frame" x="8" y="0.0" width="359" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="FpG-5e-MHT"/>
</constraints>
@@ -68,17 +72,17 @@
<tableViewSection headerTitle="" id="rgl-Lm-uDH">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ybX-Eh-Hbx">
- <rect key="frame" x="0.0" y="158" width="600" height="44"/>
+ <rect key="frame" x="0.0" y="164" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ybX-Eh-Hbx" id="uI9-fK-205">
- <rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t37-4W-6F4">
- <rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
+ <rect key="frame" x="8" y="0.0" width="359" height="43"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<state key="normal" title="Connect">
- <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+ <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="connectButtonWasPressed:" destination="l5Q-ZP-1BO" eventType="touchUpInside" id="tgb-10-M4m"/>
@@ -87,9 +91,9 @@
</subviews>
<constraints>
<constraint firstItem="t37-4W-6F4" firstAttribute="top" secondItem="uI9-fK-205" secondAttribute="top" id="IfU-4k-EXx"/>
- <constraint firstItem="t37-4W-6F4" firstAttribute="leading" secondItem="uI9-fK-205" secondAttribute="leadingMargin" constant="-8" id="cc3-uk-9fL"/>
+ <constraint firstItem="t37-4W-6F4" firstAttribute="leading" secondItem="uI9-fK-205" secondAttribute="leadingMargin" id="cc3-uk-9fL"/>
<constraint firstAttribute="bottom" secondItem="t37-4W-6F4" secondAttribute="bottom" id="hnD-4g-xvT"/>
- <constraint firstAttribute="trailingMargin" secondItem="t37-4W-6F4" secondAttribute="trailing" constant="-8" id="j4p-fi-0LP"/>
+ <constraint firstAttribute="trailingMargin" secondItem="t37-4W-6F4" secondAttribute="trailing" id="j4p-fi-0LP"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
diff --git a/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m b/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
index 0b0a785cc..17ee2ae19 100644
--- a/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
+++ b/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
@@ -73,7 +73,7 @@
- (void)proxyManagerDidChangeState:(ProxyState)newState {
UIColor* newColor = nil;
NSString* newTitle = nil;
-
+
switch (newState) {
case ProxyStateStopped: {
newColor = [UIColor redColor];
@@ -89,11 +89,11 @@
} break;
default: break;
}
-
- if (newColor && newTitle) {
+
+ if (newColor || newTitle) {
dispatch_async(dispatch_get_main_queue(), ^{
- self.connectTableViewCell.backgroundColor = newColor;
- self.connectButton.titleLabel.text = newTitle;
+ [self.connectTableViewCell setBackgroundColor:newColor];
+ [self.connectButton setTitle:newTitle forState:UIControlStateNormal];
});
}
}
diff --git a/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m b/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
index 330e87287..7861bb321 100644
--- a/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
+++ b/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
@@ -122,10 +122,10 @@
default: break;
}
- if (newColor && newTitle) {
+ if (newColor || newTitle) {
dispatch_async(dispatch_get_main_queue(), ^{
- self.connectTableViewCell.backgroundColor = newColor;
- self.connectButton.titleLabel.text = newTitle;
+ [self.connectTableViewCell setBackgroundColor:newColor];
+ [self.connectButton setTitle:newTitle forState:UIControlStateNormal];
});
}
}
diff --git a/SmartDeviceLink_Example/Classes/ProxyManager.m b/SmartDeviceLink_Example/Classes/ProxyManager.m
index 55dbe2a3a..7096f4bd9 100644
--- a/SmartDeviceLink_Example/Classes/ProxyManager.m
+++ b/SmartDeviceLink_Example/Classes/ProxyManager.m
@@ -15,6 +15,8 @@ NSString *const SDLAppId = @"9999";
NSString *const PointingSoftButtonArtworkName = @"PointingSoftButtonIcon";
NSString *const MainGraphicArtworkName = @"MainArtwork";
+BOOL const ShouldRestartOnDisconnect = NO;
+
typedef NS_ENUM(NSUInteger, SDLHMIFirstState) {
SDLHMIFirstStateNone,
SDLHMIFirstStateNonNone,
@@ -94,11 +96,12 @@ NS_ASSUME_NONNULL_BEGIN
if (!success) {
NSLog(@"SDL errored starting up: %@", error);
[weakSelf sdlex_updateProxyState:ProxyStateStopped];
- } else {
- [weakSelf sdlex_updateProxyState:ProxyStateConnected];
+ return;
}
+
+ [weakSelf sdlex_updateProxyState:ProxyStateConnected];
- [self setupPermissionsCallbacks];
+ [weakSelf setupPermissionsCallbacks];
if ([weakSelf.sdlManager.hmiLevel isEqualToEnum:[SDLHMILevel FULL]]) {
[weakSelf showInitialData];
@@ -107,6 +110,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)reset {
+ [self sdlex_updateProxyState:ProxyStateStopped];
[self.sdlManager stop];
}
@@ -354,6 +358,9 @@ NS_ASSUME_NONNULL_BEGIN
self.firstTimeState = SDLHMIFirstStateNone;
self.initialShowState = SDLHMIInitialShowStateNone;
_state = ProxyStateStopped;
+ if (ShouldRestartOnDisconnect) {
+ [self startManager];
+ }
}
- (void)hmiLevel:(SDLHMILevel *)oldLevel didChangeToLevel:(SDLHMILevel *)newLevel {