diff options
author | Joel Fischer <joeljfischer@gmail.com> | 2017-01-26 16:09:11 -0500 |
---|---|---|
committer | Joel Fischer <joeljfischer@gmail.com> | 2017-01-26 16:09:11 -0500 |
commit | ba79fb669f316b89d615feb83d29c6af2e1f5e6e (patch) | |
tree | be7a288c12bd3a0981afd0ec7b3dd96ec811ce31 | |
parent | b61b16ee4b7a57653b1daeffd8117bc1bedd559f (diff) | |
parent | a3eef8de162910a0c02a9a005b692c4172a153b1 (diff) | |
download | sdl_ios-ba79fb669f316b89d615feb83d29c6af2e1f5e6e.tar.gz |
Merge branch 'master' into hotfix/issue_512_debug_tool
# Conflicts:
# SmartDeviceLink/SDLLifecycleManager.m
10 files changed, 149 insertions, 90 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 1c565451a..3436b8844 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"; @@ -87,7 +89,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]; @@ -110,25 +112,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]; } } @@ -148,17 +139,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]; @@ -169,12 +185,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]; @@ -191,7 +215,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; } @@ -275,7 +299,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]; }]; } @@ -343,7 +367,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); @@ -380,7 +404,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; @@ -425,11 +449,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 { @@ -456,7 +484,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 { |