summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuller, Alexander (A.) <amulle19@ford.com>2017-01-26 15:00:01 -0800
committerMuller, Alexander (A.) <amulle19@ford.com>2017-01-26 15:00:01 -0800
commitc69e93b965646ad240fde10303a3f1cb31be1dc8 (patch)
tree67b732e8884077ae1596c4458e647c68d94d0a50
parent3784cd5327c143cde3c060b383a074b62aef19e4 (diff)
parenta3eef8de162910a0c02a9a005b692c4172a153b1 (diff)
downloadsdl_ios-c69e93b965646ad240fde10303a3f1cb31be1dc8.tar.gz
Merge remote-tracking branch 'origin/master' into develop
* origin/master: Fixed issue with retain cycle within the dispatch_after block. Fix double semi-colon Re-add reconnecting state Don’t auto-reconnect in example project Cleaned up ProxyManager startWithReadyHandler: In order to restart properly, we need to start only after managerDidDisconnect (per new documentation). Adding a fix to restarting the proxy around an Apple Bug. Adding a note about stopping SDLManager. Removing Reconnecting state and instead using started. Updated lifecycle manager states to handle stopping the manager correctly. Fixed issue with stopping the proxy didn't actually stop it. # Conflicts: # SmartDeviceLink-iOS.xcodeproj/project.pbxproj # SmartDeviceLink/SDLLifecycleManager.m
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.h6
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m102
-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
9 files changed, 147 insertions, 90 deletions
diff --git a/SmartDeviceLink/SDLLifecycleManager.h b/SmartDeviceLink/SDLLifecycleManager.h
index 4737354cc..7d7c3d2e1 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 e8f5e041c..f8a851cf6 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -42,8 +42,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";
@@ -85,7 +87,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];
@@ -107,25 +109,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];
}
}
@@ -145,17 +136,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";
[SDLDebugTool logInfo:@"Stopping Proxy"];
self.proxy = nil;
- [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);
@@ -371,7 +395,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;
@@ -398,11 +422,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 {
@@ -429,7 +457,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 64d1748bb..e42f1cd19 100644
--- a/SmartDeviceLink/SDLManager.h
+++ b/SmartDeviceLink/SDLManager.h
@@ -94,6 +94,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 79f79d317..8b0a276d4 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 6aac2f59f..d0fef72d1 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 isEqualToString:SDLHMILevelFull]) {
[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 {