├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md ├── RPC Builder-Info.plist ├── RPC Builder.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── RPC Builder.xcworkspace └── contents.xcworkspacedata ├── RPC Builder ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── AppIcon6.png │ │ ├── AppIcon6@2x.png │ │ ├── AppIcon@2x.png │ │ ├── AppIcon@3x.png │ │ ├── Contents.json │ │ ├── Settings.png │ │ ├── Settings@2x.png │ │ ├── Settings@3x.png │ │ ├── Spotlight@2x.png │ │ └── Spotlight@3x.png │ ├── Brand Assets.launchimage │ │ └── Contents.json │ ├── Contents.json │ ├── Modules │ │ ├── AudioPassThru.imageset │ │ │ ├── AudioPassThru@2x.png │ │ │ ├── AudioPassThru@3x.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── Streaming.imageset │ │ │ ├── Contents.json │ │ │ ├── Streaming@2x.png │ │ │ └── Streaming@3x.png │ ├── Nav Icons │ │ ├── Contents.json │ │ ├── audioFile.imageset │ │ │ ├── Contents.json │ │ │ ├── audioFile@2x.png │ │ │ └── audioFile@3x.png │ │ └── settings.imageset │ │ │ ├── Contents.json │ │ │ ├── settings@2x-2.png │ │ │ └── settings@3x-2.png │ ├── RPC Types │ │ ├── Contents.json │ │ ├── add.imageset │ │ │ ├── Contents.json │ │ │ ├── add@2x.png │ │ │ └── add@3x.png │ │ ├── delete.imageset │ │ │ ├── Contents.json │ │ │ ├── delete@2x.png │ │ │ └── delete@3x.png │ │ ├── new.imageset │ │ │ ├── Contents.json │ │ │ ├── new@2x.png │ │ │ └── new@3x.png │ │ ├── other.imageset │ │ │ ├── Contents.json │ │ │ ├── other@2x.png │ │ │ └── other@3x.png │ │ ├── subscribe.imageset │ │ │ ├── Contents.json │ │ │ ├── subscribe@2x.png │ │ │ └── subscribe@3x.png │ │ ├── ui.imageset │ │ │ ├── Contents.json │ │ │ ├── ui@2x.png │ │ │ └── ui@3x.png │ │ └── unsubscribe.imageset │ │ │ ├── Contents.json │ │ │ ├── unsubscribe@2x.png │ │ │ └── unsubscribe@3x.png │ ├── SDLAppIcon.imageset │ │ ├── Contents.json │ │ └── appIcon70x70.png │ ├── Tab Bar Icons │ │ ├── Console.imageset │ │ │ ├── Contents.json │ │ │ ├── consoleTab@2x.png │ │ │ └── consoleTab@3x.png │ │ ├── Contents.json │ │ ├── Modules.imageset │ │ │ ├── Contents.json │ │ │ ├── Modules@2x.png │ │ │ └── Modules@3x.png │ │ ├── Modules_Selected.imageset │ │ │ ├── Contents.json │ │ │ ├── Modules_Selected@2x.png │ │ │ └── Modules_Selected@3x.png │ │ ├── RPCs.imageset │ │ │ ├── Contents.json │ │ │ ├── rpcTab@2x.png │ │ │ └── rpcTab@3x.png │ │ └── RPCs_Selected.imageset │ │ │ ├── Contents.json │ │ │ ├── RPCs_Selected@2x.png │ │ │ └── RPCs_Selected@3x.png │ ├── chevron.imageset │ │ ├── Contents.json │ │ └── chevronAccessory@2x.png │ └── placeholder.imageset │ │ ├── Contents.json │ │ ├── data@2x-1.png │ │ └── data@3x-1.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Data Models │ ├── RBBaseObject.h │ ├── RBBaseObject.m │ ├── RBElement.h │ ├── RBElement.m │ ├── RBEnum.h │ ├── RBEnum.m │ ├── RBFunction.h │ ├── RBFunction.m │ ├── RBLogInfo.h │ ├── RBLogInfo.m │ ├── RBParam.h │ ├── RBParam.m │ ├── RBParser.h │ ├── RBParser.m │ ├── RBSpecFile.h │ ├── RBSpecFile.m │ ├── RBStruct.h │ └── RBStruct.m ├── Info.plist ├── Mobile_API.xml ├── Modules.storyboard ├── SmartDeviceLink │ ├── RBSDLConfiguration.h │ ├── RBSDLConfiguration.m │ ├── RBSDLManager.h │ └── RBSDLManager.m ├── Utilities │ ├── Categories │ │ ├── NSData+Chunks.h │ │ ├── NSData+Chunks.m │ │ ├── NSFileWrapper+Extensions.h │ │ ├── NSFileWrapper+Extensions.m │ │ ├── NSLayoutConstraint+CopyWithZone.h │ │ ├── NSLayoutConstraint+CopyWithZone.m │ │ ├── NSString+Regex.h │ │ ├── NSString+Regex.m │ │ ├── UIAlertAction+Minimal.h │ │ ├── UIAlertAction+Minimal.m │ │ ├── UIAlertController+Minimal.h │ │ ├── UIAlertController+Minimal.m │ │ ├── UIColor+Util.h │ │ ├── UIColor+Util.m │ │ ├── UIView+Util.h │ │ └── UIView+Util.m │ ├── NSObject+Swizzle.h │ ├── NSObject+Swizzle.m │ ├── RBCamera.h │ ├── RBCamera.m │ ├── RBDeviceInformation.h │ ├── RBDeviceInformation.m │ ├── RBSettingsManager.h │ └── RBSettingsManager.m ├── View Controllers │ ├── Modules │ │ ├── Base │ │ │ ├── RBModuleViewController.h │ │ │ └── RBModuleViewController.m │ │ ├── RBAudioPassThruModuleViewController.h │ │ ├── RBAudioPassThruModuleViewController.m │ │ ├── RBStreamingModuleViewController.h │ │ └── RBStreamingModuleViewController.m │ ├── RBAppRegistrationViewController.h │ ├── RBAppRegistrationViewController.m │ ├── RBArrayViewController.h │ ├── RBArrayViewController.m │ ├── RBBaseViewController.h │ ├── RBBaseViewController.m │ ├── RBBaseViewController.xib │ ├── RBConsoleViewController.h │ ├── RBConsoleViewController.m │ ├── RBFilePickerViewController.h │ ├── RBFilePickerViewController.m │ ├── RBFunctionViewController.h │ ├── RBFunctionViewController.m │ ├── RBFunctionsViewController.h │ ├── RBFunctionsViewController.m │ ├── RBModulesTableViewController.h │ ├── RBModulesTableViewController.m │ ├── RBScrollViewController.h │ ├── RBScrollViewController.m │ ├── RBSettingsViewController.h │ ├── RBSettingsViewController.m │ ├── RBSpecFilesViewController.h │ ├── RBSpecFilesViewController.m │ ├── RBStructViewController.h │ └── RBStructViewController.m ├── Views │ ├── UILabel │ │ ├── RBNameLabel.h │ │ └── RBNameLabel.m │ ├── UISwitch │ │ ├── RBSwitch.h │ │ └── RBSwitch.m │ ├── UITableViewCell │ │ ├── RBBaseTableViewCell.h │ │ ├── RBBaseTableViewCell.m │ │ ├── RBLogInfoTableViewCell.h │ │ ├── RBLogInfoTableViewCell.m │ │ ├── RBModuleTableViewCell.h │ │ └── RBModuleTableViewCell.m │ ├── UITextField │ │ ├── RBElementTextField.h │ │ ├── RBElementTextField.m │ │ ├── RBParamTextField.h │ │ ├── RBParamTextField.m │ │ ├── RBTextField.h │ │ └── RBTextField.m │ └── UIView │ │ ├── RBFileView.h │ │ ├── RBFileView.m │ │ ├── RBParamView.h │ │ ├── RBParamView.m │ │ ├── RBView.h │ │ └── RBView.m └── main.m └── ReadmeFiles ├── AddCommand.png ├── Connecting.png ├── Console-RAI.png ├── Console.png ├── EnabledDisabled.png ├── MainField.png ├── Modules.png ├── RPCs.png ├── RegisterAppInterface.png ├── Settings.png └── Show.png /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to SDL Projects 2 | 3 | Third party contributions are essential for making SDL great. However, we do have a few guidelines we need contributors to follow. 4 | 5 | ### Issues 6 | If writing a bug report, please make sure it has enough info. Include all relevant information. 7 | 8 | If requesting a feature, understand that we appreciate the input! However, it may not immediately fit our roadmap, and it may take a while for us to get to your request. 9 | 10 | ### Gitflow 11 | We use Gitflow as our branch management system. Please follow gitflow's guidelines while contributing to any SDL project. 12 | 13 | ### Pull Requests 14 | * Please follow the repository's for all code and documentation. 15 | * All feature branches should be based on `develop` and have the format `feature/branch_name`. 16 | * Minor bug fixes, that is bug fixes that do not change, add, or remove any public API, should be based on `master` and have the format `hotfix/branch_name`. 17 | * All pull requests should implement a single feature or fix a single bug. Pull Requests that involve multiple changes (it is our discretion what precisely this means) will be rejected with a reason. 18 | * All commits should separated into logical units, i.e. unrelated changes should be in different commits within a pull request. 19 | * Work in progress pull requests should have "[WIP]" in front of the Pull Request title. When you believe the pull request is ready to merge, remove this tag and @mention the appropriate SDL team to schedule a review. 20 | * All new code *must* include unit tests. Bug fixes should have a test that fails previously and now passes. All new features should be covered. If your code does not have tests, or regresses old tests, it will be rejected. 21 | * A great example of a pull request can be found here. 22 | 23 | ### Contributor's License Agreement (CLA) 24 | In order to accept Pull Requests from contributors, you must first sign [the Contributor's License Agreement](https://docs.google.com/forms/d/1VNR8EUd5b46cQ7uNbCq1fJmnu0askNpUp5dudLKRGpU/viewform). If you need to make a change to information that you entered, [please contact us](mailto:justin@livio.io). 25 | 26 | ### Repository Specific Guidelines 27 | * iOS Style Guide 28 | * Please document all code written using [Objective-C style documentation](http://nshipster.com/documentation/) for methods (we use [VVDocumenter](https://github.com/onevcat/VVDocumenter-Xcode) for methods and use inline code comments where it makes sense, i.e. for non-obvious code chunks. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | [Delete any non-applicable sections, but we may ask for more information.] 2 | 3 | ### Bug Report 4 | [Summary] 5 | 6 | ##### Reproduction Steps 7 | 1. [Step 1] 8 | 1. [Step 2] 9 | 1. [Step 3] 10 | 11 | ##### Expected Behavior 12 | [Some expected behavior] 13 | 14 | ##### Observed Behavior 15 | [Some observed behavior] 16 | 17 | ##### OS & Version Information 18 | * iOS Version: [What version of iOS is the RPC Builder running on when the bug occurred] 19 | * SDL Version: [What version of the library has this bug been seen on] 20 | * Testing Against: [What you tested with to observe this behavior] 21 | 22 | ##### Test Case, Sample Code, and / or Example App 23 | [Paste a link to a PR, gist, or other code that exemplifies this behavior] 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes #[issue number] 2 | 3 | This PR is **[ready / not ready]** for review. 4 | 5 | ### Risk 6 | This PR makes **[no / minor / major]** API changes. 7 | 8 | ### Testing Plan 9 | [Describe how you plan to unit test the changes in this PR] 10 | 11 | ### Summary 12 | [Summary of PR changes] 13 | 14 | ### Changelog 15 | ##### Breaking Changes 16 | * [Breaking change info] 17 | 18 | ##### Enchancements 19 | * [Enchancement info] 20 | 21 | ##### Bug Fixes 22 | * [Bug Fix Info] 23 | 24 | ### Tasks Remaining: 25 | - [ ] [Task 1] 26 | - [ ] [Task 2] 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | Pods/ 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0 Release Notes 2 | * Initial Commit 3 | 4 | # 1.0.1 Release Notes 5 | ## Bug Fixes 6 | * Fixed issue relating to selecting an enumeration in an array property. 7 | 8 | ## Enhancements 9 | * When proxy connects, enable ability to keep app awake. 10 | 11 | # 1.0.2 Release Notes 12 | ## Bug Fixes 13 | * Fixed issue with requests with Float type parameters not being shown. 14 | * Removed compilation warnings revolving around iOS 6 autolayout changes and missing assets. 15 | 16 | ## Other 17 | * RPC Builder now uses SmartDeviceLink v4.1. 18 | * Contained MOBILE_API.xml updated to commit 2b02a8e. Actual file can be seen [here](https://github.com/smartdevicelink/sdl_core/blob/master/src/components/interfaces/MOBILE_API.xml). 19 | * Added Contributions section to README to give credit where credit is due. 20 | 21 | # 1.1.0 Release Notes 22 | ## Enhancements 23 | * Added ability for developers to create modules to do more advanced testing of RPCs. 24 | * Added Streaming Module for testing audio and video streaming. 25 | 26 | # 1.2.0 Release Notes 27 | ## Enhancements 28 | * Added Audio Capture Module for testing PerformAudioPassThru RPC. 29 | 30 | # 1.2.1 Release Notes 31 | ## Bug Fixes 32 | * Fixed issue with nested arrays in structs in functions would not save correctly. 33 | 34 | # 1.2.2 Release Notes 35 | ## Enhancements 36 | * Added color coded responses for easier reading in the Console. 37 | 38 | # 1.2.3 Release Notes 39 | ## Bug Fixes 40 | * Fixed issue with not all types of array-based parameters working. 41 | * Fixed issue with not working with all property types. 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 SmartDeviceLink Consortium, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '6.0' 2 | use_frameworks! 3 | 4 | target "RPC Builder" do 5 | pod 'SmartDeviceLink', :git=> 'https://github.com/smartdevicelink/sdl_ios.git', :tag => '4.6.0-rc.2' 6 | end 7 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SmartDeviceLink (4.6.0-rc.2) 3 | 4 | DEPENDENCIES: 5 | - SmartDeviceLink (from `https://github.com/smartdevicelink/sdl_ios.git`, tag `4.6.0-rc.2`) 6 | 7 | EXTERNAL SOURCES: 8 | SmartDeviceLink: 9 | :git: https://github.com/smartdevicelink/sdl_ios.git 10 | :tag: 4.6.0-rc.2 11 | 12 | CHECKOUT OPTIONS: 13 | SmartDeviceLink: 14 | :git: https://github.com/smartdevicelink/sdl_ios.git 15 | :tag: 4.6.0-rc.2 16 | 17 | SPEC CHECKSUMS: 18 | SmartDeviceLink: 8311051cf785019ded9a43ccf04dce28dea603c8 19 | 20 | PODFILE CHECKSUM: d90c9fe8822e8a70c0423b8014f1383583f32234 21 | 22 | COCOAPODS: 1.3.0.beta.2 23 | -------------------------------------------------------------------------------- /RPC Builder-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIcons 10 | 11 | CFBundleIcons~ipad 12 | 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedExternalAccessoryProtocols 38 | 39 | com.ford.sync.prot0 40 | com.smartdevicelink.prot0 41 | com.smartdevicelink.prot1 42 | com.smartdevicelink.prot2 43 | com.smartdevicelink.prot3 44 | com.smartdevicelink.prot4 45 | com.smartdevicelink.prot5 46 | com.smartdevicelink.prot6 47 | com.smartdevicelink.prot7 48 | com.smartdevicelink.prot8 49 | com.smartdevicelink.prot9 50 | com.smartdevicelink.prot10 51 | com.smartdevicelink.prot11 52 | com.smartdevicelink.prot12 53 | com.smartdevicelink.prot13 54 | com.smartdevicelink.prot14 55 | com.smartdevicelink.prot15 56 | com.smartdevicelink.prot16 57 | com.smartdevicelink.prot17 58 | com.smartdevicelink.prot18 59 | com.smartdevicelink.prot19 60 | com.smartdevicelink.prot20 61 | com.smartdevicelink.prot21 62 | com.smartdevicelink.prot22 63 | com.smartdevicelink.prot23 64 | com.smartdevicelink.prot24 65 | com.smartdevicelink.prot25 66 | com.smartdevicelink.prot26 67 | com.smartdevicelink.prot27 68 | com.smartdevicelink.prot28 69 | com.smartdevicelink.prot29 70 | 71 | UISupportedInterfaceOrientations 72 | 73 | UIInterfaceOrientationPortrait 74 | UIInterfaceOrientationLandscapeLeft 75 | UIInterfaceOrientationLandscapeRight 76 | 77 | UISupportedInterfaceOrientations~ipad 78 | 79 | UIInterfaceOrientationPortrait 80 | UIInterfaceOrientationPortraitUpsideDown 81 | UIInterfaceOrientationLandscapeLeft 82 | UIInterfaceOrientationLandscapeRight 83 | 84 | UIFileSharingEnabled 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /RPC Builder.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RPC Builder.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RPC Builder/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface AppDelegate : UIResponder 9 | 10 | @property (strong, nonatomic) UIWindow *window; 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /RPC Builder/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RPC Builder 4 | // 5 | 6 | #import "AppDelegate.h" 7 | #import "RBSDLManager.h" 8 | 9 | @interface AppDelegate () 10 | 11 | @end 12 | 13 | @implementation AppDelegate 14 | 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 17 | 18 | if ([self.window.rootViewController isKindOfClass:[UITabBarController class]]) { 19 | UITabBarController* tabBarController = (UITabBarController*)self.window.rootViewController; 20 | for (UIViewController* viewController in tabBarController.viewControllers) { 21 | if ([viewController isKindOfClass:[UINavigationController class]]) { 22 | UINavigationController* navigationController = (UINavigationController*)viewController; 23 | for (UIViewController* childViewController in navigationController.viewControllers) { 24 | [childViewController view]; 25 | } 26 | } 27 | } 28 | } 29 | 30 | [self.window makeKeyAndVisible]; 31 | 32 | if (![[RBSDLManager sharedManager] isConnected]) { 33 | [[RBSDLManager sharedManager] presentSettingsViewController]; 34 | } 35 | 36 | return YES; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon6.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon6@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Settings.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Settings@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Settings@3x.png", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Spotlight@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Spotlight@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "57x57", 35 | "idiom" : "iphone", 36 | "filename" : "AppIcon6.png", 37 | "scale" : "1x" 38 | }, 39 | { 40 | "size" : "57x57", 41 | "idiom" : "iphone", 42 | "filename" : "AppIcon6@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "AppIcon@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "AppIcon@3x.png", 55 | "scale" : "3x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/Settings@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/Spotlight@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/AppIcon.appiconset/Spotlight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/AppIcon.appiconset/Spotlight@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Brand Assets.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | 4 | ], 5 | "info" : { 6 | "version" : 1, 7 | "author" : "xcode" 8 | } 9 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/AudioPassThru.imageset/AudioPassThru@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Modules/AudioPassThru.imageset/AudioPassThru@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/AudioPassThru.imageset/AudioPassThru@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Modules/AudioPassThru.imageset/AudioPassThru@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/AudioPassThru.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "AudioPassThru@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "AudioPassThru@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/Streaming.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Streaming@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Streaming@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/Streaming.imageset/Streaming@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Modules/Streaming.imageset/Streaming@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Modules/Streaming.imageset/Streaming@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Modules/Streaming.imageset/Streaming@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/audioFile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "audioFile@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "audioFile@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/audioFile.imageset/audioFile@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Nav Icons/audioFile.imageset/audioFile@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/audioFile.imageset/audioFile@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Nav Icons/audioFile.imageset/audioFile@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/settings.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "settings@2x-2.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "settings@3x-2.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/settings.imageset/settings@2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Nav Icons/settings.imageset/settings@2x-2.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Nav Icons/settings.imageset/settings@3x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Nav Icons/settings.imageset/settings@3x-2.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/add.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "add@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "add@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/add.imageset/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/add.imageset/add@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/add.imageset/add@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/add.imageset/add@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/delete.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "delete@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "delete@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/delete.imageset/delete@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/delete.imageset/delete@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/delete.imageset/delete@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/delete.imageset/delete@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/new.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "new@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "new@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/new.imageset/new@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/new.imageset/new@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/new.imageset/new@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/new.imageset/new@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/other.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "other@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "other@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/other.imageset/other@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/other.imageset/other@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/other.imageset/other@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/other.imageset/other@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/subscribe.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "subscribe@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "subscribe@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/subscribe.imageset/subscribe@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/subscribe.imageset/subscribe@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/subscribe.imageset/subscribe@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/subscribe.imageset/subscribe@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/ui.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ui@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "ui@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/ui.imageset/ui@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/ui.imageset/ui@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/ui.imageset/ui@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/ui.imageset/ui@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/unsubscribe.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "unsubscribe@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "unsubscribe@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/unsubscribe.imageset/unsubscribe@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/unsubscribe.imageset/unsubscribe@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/RPC Types/unsubscribe.imageset/unsubscribe@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/RPC Types/unsubscribe.imageset/unsubscribe@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/SDLAppIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "appIcon70x70.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/SDLAppIcon.imageset/appIcon70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/SDLAppIcon.imageset/appIcon70x70.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Console.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "consoleTab@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "consoleTab@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Console.imageset/consoleTab@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Console.imageset/consoleTab@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Console.imageset/consoleTab@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Console.imageset/consoleTab@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Modules@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Modules@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules.imageset/Modules@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Modules.imageset/Modules@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules.imageset/Modules@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Modules.imageset/Modules@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules_Selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Modules_Selected@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Modules_Selected@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules_Selected.imageset/Modules_Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Modules_Selected.imageset/Modules_Selected@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/Modules_Selected.imageset/Modules_Selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/Modules_Selected.imageset/Modules_Selected@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "rpcTab@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "rpcTab@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs.imageset/rpcTab@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs.imageset/rpcTab@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs.imageset/rpcTab@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs.imageset/rpcTab@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs_Selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "RPCs_Selected@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "RPCs_Selected@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs_Selected.imageset/RPCs_Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs_Selected.imageset/RPCs_Selected@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs_Selected.imageset/RPCs_Selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/Tab Bar Icons/RPCs_Selected.imageset/RPCs_Selected@3x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/chevron.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chevronAccessory@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/chevron.imageset/chevronAccessory@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/chevron.imageset/chevronAccessory@2x.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/placeholder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "data@2x-1.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "data@3x-1.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/placeholder.imageset/data@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/placeholder.imageset/data@2x-1.png -------------------------------------------------------------------------------- /RPC Builder/Assets.xcassets/placeholder.imageset/data@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/RPC Builder/Assets.xcassets/placeholder.imageset/data@3x-1.png -------------------------------------------------------------------------------- /RPC Builder/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBBaseObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBBaseObject.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | extern NSString* const RBNameKey; 9 | extern NSString* const RBTypeKey; 10 | extern NSString* const RBTypeStringKey; 11 | extern NSString* const RBTypeIntegerKey; 12 | extern NSString* const RBTypeLongKey; 13 | extern NSString* const RBTypeDoubleKey; 14 | extern NSString* const RBTypeFloatKey; 15 | extern NSString* const RBTypeBooleanKey; 16 | extern NSString* const RBTypeBooleanTrueValue; 17 | extern NSString* const RBTypeBooleanFalseValue; 18 | extern NSString* const RBDefaultValueKey; 19 | extern NSString* const RBIsMandatoryKey; 20 | extern NSString* const RBIsArrayKey; 21 | extern NSString* const RBMinValueKey; 22 | extern NSString* const RBMaxValueKey; 23 | extern NSString* const RBMaxLengthKey; 24 | extern NSString* const RBFunctionIDKey; 25 | extern NSString* const RBMessageTypeKey; 26 | 27 | @interface RBBaseObject : NSObject 28 | 29 | + (instancetype)objectWithDictionary:(NSDictionary*)dictionary; 30 | - (instancetype)initWithDictionary:(NSDictionary*)dictionary; 31 | 32 | - (void)handleKey:(NSString*)key value:(id)value; 33 | 34 | - (void)appendDescription:(NSString *)description; 35 | 36 | @property (nonatomic, readonly) NSString* name; 37 | @property (nonatomic, readonly) NSDictionary* properties; 38 | @property (nonatomic, readonly) NSString* objectDescription; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBBaseObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBBaseObject.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseObject.h" 7 | 8 | NSString* const RBNameKey = @"name"; 9 | NSString* const RBTypeKey = @"type"; 10 | NSString* const RBTypeStringKey = @"String"; 11 | NSString* const RBTypeIntegerKey = @"Integer"; 12 | NSString* const RBTypeLongKey = @"Long"; 13 | NSString* const RBTypeDoubleKey = @"Double"; 14 | NSString* const RBTypeFloatKey = @"Float"; 15 | NSString* const RBTypeBooleanKey = @"Boolean"; 16 | NSString* const RBTypeBooleanTrueValue = @"true"; 17 | NSString* const RBTypeBooleanFalseValue = @"false"; 18 | NSString* const RBDefaultValueKey = @"defvalue"; 19 | NSString* const RBIsMandatoryKey = @"mandatory"; 20 | NSString* const RBIsArrayKey = @"array"; 21 | NSString* const RBMinValueKey = @"minvalue"; 22 | NSString* const RBMaxValueKey = @"maxvalue"; 23 | NSString* const RBMaxLengthKey = @"maxlength"; 24 | NSString* const RBFunctionIDKey = @"functionID"; 25 | NSString* const RBMessageTypeKey = @"messagetype"; 26 | 27 | @interface RBBaseObject () 28 | 29 | @property (nonatomic, strong) NSMutableDictionary* mutableProperties; 30 | @property (nonatomic, strong) NSMutableString* mutableDescription; 31 | @property (nonatomic, strong) NSMutableString* mutableObjectDescription; 32 | 33 | @end 34 | 35 | @implementation RBBaseObject 36 | 37 | + (instancetype)objectWithDictionary:(NSDictionary*)dictionary { 38 | return [[[self class] alloc] initWithDictionary:dictionary]; 39 | } 40 | 41 | - (instancetype)initWithDictionary:(NSDictionary*)dictionary { 42 | if (self = [super init]) { 43 | _mutableProperties = [NSMutableDictionary dictionary]; 44 | _mutableDescription = [NSMutableString string]; 45 | _mutableObjectDescription = [NSMutableString string]; 46 | for (NSString* key in dictionary.allKeys) { 47 | [self handleKey:key 48 | value:dictionary[key]]; 49 | } 50 | } 51 | return self; 52 | } 53 | 54 | #pragma mark - Public Functions 55 | - (void)appendDescription:(NSString *)description { 56 | if (description.length) { 57 | description = [description stringByReplacingOccurrencesOfString:@"\\s{2,}" 58 | withString:@"" 59 | options:NSRegularExpressionSearch 60 | range:NSMakeRange(0, description.length)]; 61 | [_mutableObjectDescription appendString:description]; 62 | [_mutableDescription appendString:description]; 63 | } 64 | } 65 | 66 | - (void)handleKey:(NSString*)key value:(id)value { 67 | if ([key isEqualToString:RBNameKey]) { 68 | _name = value; 69 | } else { 70 | _mutableProperties[key] = value; 71 | } 72 | } 73 | 74 | #pragma mark - Getters 75 | - (NSString*)description { 76 | NSString* properties = self.properties.count ? [NSString stringWithFormat:@", properties: %@", self.properties] : @""; 77 | NSString* description = _mutableDescription.length ? [NSString stringWithFormat:@", description: %@", _mutableDescription] : @""; 78 | return [NSString stringWithFormat:@"<%@: %@%@%@>", NSStringFromClass(self.class), _name, properties, description]; 79 | } 80 | 81 | - (NSString*)objectDescription { 82 | return _mutableObjectDescription.length ? [_mutableObjectDescription copy] : nil; 83 | } 84 | 85 | - (NSDictionary*)properties { 86 | return [_mutableProperties copy]; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBElement.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBElement.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseObject.h" 7 | 8 | @interface RBElement : RBBaseObject 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBElement.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBElement.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBElement.h" 7 | 8 | @implementation RBElement 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBEnum.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBEnum.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseObject.h" 7 | 8 | @class RBElement; 9 | 10 | @interface RBEnum : RBBaseObject 11 | 12 | - (void)addElement:(RBElement*)element; 13 | 14 | @property (nonatomic, readonly) NSArray* elements; 15 | 16 | @end -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBEnum.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBEnum.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBEnum.h" 7 | 8 | @interface RBEnum () 9 | 10 | @property (nonatomic, strong) NSMutableArray* mutableElements; 11 | 12 | @end 13 | 14 | @implementation RBEnum 15 | 16 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary { 17 | if (self = [super initWithDictionary:dictionary]) { 18 | _mutableElements = [NSMutableArray array]; 19 | } 20 | return self; 21 | } 22 | 23 | #pragma mark - Public Functions 24 | - (void)addElement:(RBElement *)element { 25 | [_mutableElements addObject:element]; 26 | } 27 | 28 | #pragma mark - Getters 29 | - (NSString*)description { 30 | NSMutableString* mutableDescription = [super.description mutableCopy]; 31 | if (self.elements.count) { 32 | [mutableDescription insertString:[NSString stringWithFormat:@", elements: %@", self.elements] 33 | atIndex:mutableDescription.length-1]; 34 | } 35 | return [mutableDescription copy]; 36 | } 37 | 38 | - (NSArray*)elements { 39 | return [_mutableElements copy]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBFunction.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBFunction.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBStruct.h" 7 | 8 | @interface RBFunction : RBStruct 9 | 10 | @property (nonatomic, readonly) NSString* functionID; 11 | @property (nonatomic, readonly) NSString* messageType; 12 | 13 | @property (nonatomic, readonly) UIImage* image; 14 | 15 | @property (nonatomic, readonly) BOOL requiresBulkData; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBFunction.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBFunction.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBFunction.h" 7 | 8 | @interface RBFunction () 9 | 10 | @property (nonatomic, strong, readonly) NSArray* UIFunctionNames; 11 | @property (nonatomic, strong, readonly) NSArray* bulkDataFunctionNames; 12 | 13 | @end 14 | 15 | @implementation RBFunction 16 | 17 | @synthesize image = _image; 18 | 19 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary { 20 | if (self = [super initWithDictionary:dictionary]) { 21 | _requiresBulkData = [self.bulkDataFunctionNames containsObject:self.name]; 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - Overrides 27 | - (void)handleKey:(NSString*)key value:(id)value { 28 | if ([key isEqualToString:RBFunctionIDKey]) { 29 | _functionID = value; 30 | } else if ([key isEqualToString:RBMessageTypeKey]) { 31 | _messageType = value; 32 | } else { 33 | [super handleKey:key 34 | value:value]; 35 | } 36 | } 37 | 38 | #pragma mark - Getters 39 | - (NSString*)description { 40 | NSMutableString* mutableDescription = [super.description mutableCopy]; 41 | NSString* parameters = self.parameters.count ? [NSString stringWithFormat:@", parameters: %@", self.parameters] : @""; 42 | [mutableDescription insertString:[NSString stringWithFormat:@", functionID: %@, messageType: %@%@", _functionID, _messageType, parameters] atIndex:mutableDescription.length-1]; 43 | return [mutableDescription copy]; 44 | } 45 | 46 | - (UIImage*)image { 47 | if (!_image) { 48 | if ([self.name hasPrefix:@"Add"] 49 | || [self.name hasPrefix:@"Create"]) { 50 | _image = [UIImage imageNamed:@"add"]; 51 | } else if ([self.name hasPrefix:@"Delete"]) { 52 | _image = [UIImage imageNamed:@"delete"]; 53 | } else if ([self.name hasPrefix:@"Subscribe"]) { 54 | _image = [UIImage imageNamed:@"subscribe"]; 55 | } else if ([self.name hasPrefix:@"Un"]) { 56 | _image = [UIImage imageNamed:@"unsubscribe"]; 57 | } else if ([self.name hasPrefix:@"Set"] 58 | || [self.name hasPrefix:@"Alert"] 59 | || [self.UIFunctionNames containsObject:self.name]) { 60 | _image = [UIImage imageNamed:@"ui"]; 61 | } else { 62 | _image = [UIImage imageNamed:@"other"]; 63 | } 64 | } 65 | return _image; 66 | } 67 | 68 | #pragma - mark Private 69 | - (NSArray*)UIFunctionNames { 70 | static NSArray* UIFunctionNames = nil; 71 | static dispatch_once_t onceToken; 72 | dispatch_once(&onceToken, ^{ 73 | if (!UIFunctionNames) { 74 | UIFunctionNames = @[ 75 | @"Show", 76 | @"SendLocation", 77 | @"Slider", 78 | @"Speak", 79 | @"PerformInteraction", 80 | @"PerformAudioPassThru", 81 | @"ScrollableMessage" 82 | ]; 83 | } 84 | }); 85 | return UIFunctionNames; 86 | } 87 | 88 | - (NSArray*)bulkDataFunctionNames { 89 | static NSArray* bulkDataFunctionNames = nil; 90 | static dispatch_once_t onceToken; 91 | dispatch_once(&onceToken, ^{ 92 | if (!bulkDataFunctionNames) { 93 | bulkDataFunctionNames = @[@"PutFile"]; 94 | } 95 | }); 96 | return bulkDataFunctionNames; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBLogInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBLogInfo.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/14/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, RBLogInfoType) { 12 | RBLogInfoTypeSystem, 13 | RBLogInfoTypeNotification, 14 | RBLogInfoTypeRequest, 15 | RBLogInfoTypeResponse 16 | }; 17 | 18 | @interface RBLogInfo : NSObject 19 | 20 | + (instancetype)logInfoWithString:(NSString*)string; 21 | 22 | - (instancetype)initWithString:(NSString*)string; 23 | 24 | @property (nonatomic, readonly) NSString* title; 25 | @property (nonatomic, readonly) NSString* dateString; 26 | @property (nonatomic, readonly) NSString* message; 27 | 28 | @property (nonatomic, readonly) RBLogInfoType type; 29 | @property (nonatomic, readonly) UIColor* typeColor; 30 | 31 | @property (nonatomic, readonly) NSString* resultString; 32 | @property (nonatomic, readonly) UIColor* resultColor; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBLogInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBLogInfo.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/14/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBLogInfo.h" 10 | 11 | #import "NSString+Regex.h" 12 | #import "UIColor+Util.h" 13 | 14 | static NSString* const RBLogInfoTypeStringNotification = @"(notification)"; 15 | static NSString* const RBLogInfoTypeStringResponse = @"(response)"; 16 | static NSString* const RBLogInfoTypeStringRequest = @"(request)"; 17 | 18 | static NSString* const RBLogInfoResultTypeSuccess = @"SUCCESS"; 19 | static NSString* const RBLogInfoResultTypeAborted = @"ABORTED"; 20 | static NSString* const RBLogInfoResultTypeTimedOut = @"TIMED_OUT"; 21 | static NSString* const RBLogInfoResultTypeWarnings = @"WARNINGS"; 22 | 23 | @interface RBLogInfo () 24 | 25 | @property (nonatomic, readonly) NSRegularExpression* logTypeRegex; 26 | @property (nonatomic, readonly) NSRegularExpression* resultTypeRegex; 27 | 28 | @property (nonatomic, readonly) NSDateFormatter* dateFormatter; 29 | 30 | @end 31 | 32 | @implementation RBLogInfo 33 | 34 | + (instancetype)logInfoWithString:(NSString*)string { 35 | return [[RBLogInfo alloc] initWithString:string]; 36 | } 37 | 38 | - (instancetype)initWithString:(NSString*)string { 39 | if (self = [super init]) { 40 | _dateString = [self.dateFormatter stringFromDate:[NSDate date]]; 41 | NSString* strippedInfo = [string stringByReplacingOccurrencesOfString:@"[ \\t]+" 42 | withString:@" " 43 | options:NSRegularExpressionSearch 44 | range:NSMakeRange(0, string.length)]; 45 | NSArray* components = [strippedInfo componentsSeparatedByString:@"\n"]; 46 | _title = [components firstObject]; 47 | 48 | if (components.count > 1) { 49 | _message = [[components subarrayWithRange:NSMakeRange(1, components.count - 1)] componentsJoinedByString:@"\n"]; 50 | _resultString = [_message firstStringMatchUsingRegex:self.resultTypeRegex]; 51 | if ([_resultString isEqualToString:RBLogInfoResultTypeSuccess]) { 52 | _resultColor = [UIColor successColor]; 53 | } else if ([_resultString isEqualToString:RBLogInfoResultTypeAborted] 54 | || [_resultString isEqualToString:RBLogInfoResultTypeTimedOut] 55 | || [_resultString isEqualToString:RBLogInfoResultTypeWarnings]) { 56 | _resultColor = [UIColor warningColor]; 57 | } else { 58 | _resultColor = [UIColor errorColor]; 59 | } 60 | } else { 61 | _message = @""; 62 | } 63 | 64 | NSString* logTypeString = [_title firstStringMatchUsingRegex:self.logTypeRegex]; 65 | 66 | if ([logTypeString isEqualToString:RBLogInfoTypeStringNotification]) { 67 | _type = RBLogInfoTypeNotification; 68 | _typeColor = [UIColor notificationColor]; 69 | } else if ([logTypeString isEqualToString:RBLogInfoTypeStringRequest]) { 70 | _type = RBLogInfoTypeRequest; 71 | _typeColor = [UIColor requestColor]; 72 | } else if ([logTypeString isEqualToString:RBLogInfoTypeStringResponse]) { 73 | _type = RBLogInfoTypeResponse; 74 | _typeColor = [UIColor responseColor]; 75 | } else { 76 | _type = RBLogInfoTypeSystem; 77 | _typeColor = [UIColor systemColor]; 78 | } 79 | } 80 | return self; 81 | } 82 | 83 | #pragma mark - Private 84 | #pragma mark Getters 85 | - (NSDateFormatter*)dateFormatter { 86 | static NSDateFormatter* dateFormatter = nil; 87 | if (!dateFormatter) { 88 | dateFormatter = [[NSDateFormatter alloc] init]; 89 | dateFormatter.dateFormat = @"hh:mm:ss.SS"; 90 | } 91 | return dateFormatter; 92 | } 93 | 94 | - (NSRegularExpression*)logTypeRegex { 95 | static NSRegularExpression* regularExpression = nil; 96 | if (!regularExpression) { 97 | NSError* error = nil; 98 | regularExpression = [NSRegularExpression regularExpressionWithPattern:@"\\(\\w*\\)" 99 | options:NSRegularExpressionCaseInsensitive 100 | error:&error]; 101 | if (error) { 102 | NSLog(@"Regex error: %@", error.localizedDescription); 103 | } 104 | } 105 | return regularExpression; 106 | } 107 | 108 | - (NSRegularExpression*)resultTypeRegex { 109 | static NSRegularExpression* regularExpression = nil; 110 | if (!regularExpression) { 111 | NSError* error = nil; 112 | regularExpression = [NSRegularExpression regularExpressionWithPattern:@"resultCode = \"?(\\w*)\"?;" 113 | options:NSRegularExpressionCaseInsensitive 114 | error:&error]; 115 | if (error) { 116 | NSLog(@"Regex error: %@", error.localizedDescription); 117 | } 118 | } 119 | return regularExpression; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBParam.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBParam.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBEnum.h" 7 | #import 8 | 9 | @class RBParamView; 10 | 11 | @interface RBParam : RBEnum 12 | 13 | @property (nonatomic, readonly) NSString* type; 14 | @property (nonatomic, readonly) NSString* defaultValue; 15 | @property (nonatomic, readonly) NSNumber* minValue; 16 | @property (nonatomic, readonly) NSNumber* maxValue; 17 | @property (nonatomic, readonly) NSNumber* maxLength; 18 | @property (nonatomic, readonly) BOOL requiresArray; 19 | @property (nonatomic, readonly) BOOL isMandatory; 20 | 21 | - (RBParamView*)viewWithDelegate:(id)delegate; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBParam.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBParam.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBParam.h" 7 | #import "RBParamView.h" 8 | 9 | @implementation RBParam 10 | 11 | #pragma mark - Public 12 | - (RBParamView*)viewWithDelegate:(id)delegate { 13 | return [[RBParamView alloc] initWithParam:self 14 | delegate:delegate]; 15 | } 16 | 17 | #pragma mark - Overrides 18 | - (void)handleKey:(NSString*)key value:(id)value { 19 | if ([key isEqualToString:RBTypeKey]) { 20 | _type = value; 21 | } else if ([key isEqualToString:RBDefaultValueKey]) { 22 | _defaultValue = value; 23 | } else if ([key isEqualToString:RBIsMandatoryKey]) { 24 | _isMandatory = [value isEqualToString:RBTypeBooleanTrueValue]; 25 | } else if ([key isEqualToString:RBIsArrayKey]) { 26 | _requiresArray = [value isEqualToString:RBTypeBooleanTrueValue]; 27 | } else if ([key isEqualToString:RBMinValueKey]) { 28 | _minValue = value; 29 | } else if ([key isEqualToString:RBMaxValueKey]) { 30 | _maxValue = value; 31 | } else if ([key isEqualToString:RBMaxLengthKey]) { 32 | _maxLength = value; 33 | } else { 34 | [super handleKey:key 35 | value:value]; 36 | } 37 | } 38 | 39 | #pragma mark - Getters 40 | - (NSString*)description { 41 | NSMutableString* mutableDescription = [super.description mutableCopy]; 42 | NSString* elements = self.elements.count ? [NSString stringWithFormat:@", elements: %@", self.elements] : @""; 43 | NSString* defaultValue = _defaultValue.length ? [NSString stringWithFormat:@", default: %@", _defaultValue] : @""; 44 | [mutableDescription insertString:[NSString stringWithFormat:@", type: %@%@%@, mandatory: %@, array: %@", _type, defaultValue, elements, _isMandatory ? @"YES" : @"NO", _requiresArray ? @"YES" : @"NO"] atIndex:mutableDescription.length-1]; 45 | return [mutableDescription copy]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBParser.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import "RBStruct.h" 8 | #import "RBEnum.h" 9 | #import "RBFunction.h" 10 | #import "RBElement.h" 11 | #import "RBParam.h" 12 | 13 | typedef NS_ENUM(NSUInteger, RBParserError) { 14 | RBParserErrorURLNotFound = 404 15 | }; 16 | 17 | extern NSString* const RBParserErrorStringURLNotFound; 18 | 19 | @class RBParser; 20 | @protocol RBParserDelegate 21 | 22 | - (void)parserDidFinish:(RBParser*)parser; 23 | - (void)parserErrorOccurred:(RBParser*)parser; 24 | 25 | @end 26 | 27 | @interface RBParser : NSObject 28 | 29 | + (instancetype)sharedParser; 30 | 31 | - (void)parseSpecAtURL:(NSURL*)specURL delegate:(id)delegate; 32 | - (void)parseSpecData:(NSData*)data delegate:(id)delegate; 33 | 34 | - (RBStruct*)structOfType:(NSString*)type; 35 | - (RBEnum*)enumOfType:(NSString*)type; 36 | - (RBFunction*)functionOfType:(NSString*)type; 37 | 38 | @property (weak) id delegate; 39 | 40 | @property (nonatomic, readonly) NSArray* RPCs; 41 | @property (nonatomic, readonly) NSArray* functions; 42 | @property (nonatomic, readonly) NSArray* elements; 43 | @property (nonatomic, readonly) NSError* error; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBSpecFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBSpecFile.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @class RBSpecFile; 9 | 10 | @protocol RBSpecFileDelegate 11 | 12 | - (void)specFile:(RBSpecFile*)file fetchUrlDidFinishWithError:(NSError*)error; 13 | - (void)specFileFetchUrlDidFinish:(RBSpecFile*)file; 14 | 15 | @end 16 | 17 | @interface RBSpecFile : NSObject 18 | 19 | - (instancetype)initWithURL:(NSURL*)url; 20 | + (instancetype)fileWithURL:(NSURL*)url; 21 | 22 | - (void)fetchUrl; 23 | 24 | @property (nonatomic, readonly) NSString* fileName; 25 | @property (nonatomic, readonly) NSURL* url; 26 | @property (nonatomic, readonly) NSData* data; 27 | 28 | @property (weak) id delegate; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBSpecFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBSpecFile.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSpecFile.h" 7 | 8 | @interface RBSpecFile () 9 | 10 | @property (nonatomic, readonly) NSString* documentsPathString; 11 | 12 | @end 13 | 14 | @implementation RBSpecFile 15 | 16 | + (instancetype)fileWithURL:(NSURL*)url { 17 | return [[RBSpecFile alloc] initWithURL:url]; 18 | } 19 | 20 | - (instancetype)initWithURL:(NSURL *)url { 21 | if (self = [super init]) { 22 | _url = url; 23 | 24 | NSString *documentsPathString = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 25 | documentsPathString = [documentsPathString stringByAppendingString:@"/SpecXMLs/"]; 26 | 27 | if (![[NSFileManager defaultManager] fileExistsAtPath:documentsPathString]) { 28 | NSError* error = nil; 29 | [[NSFileManager defaultManager] createDirectoryAtPath:documentsPathString 30 | withIntermediateDirectories:NO 31 | attributes:nil 32 | error:&error]; 33 | if (error) { 34 | [self.delegate specFile:self fetchUrlDidFinishWithError:error]; 35 | } 36 | } 37 | _documentsPathString = documentsPathString; 38 | } 39 | return self; 40 | } 41 | 42 | #pragma mark - Overrides 43 | - (BOOL)isEqual:(id)object { 44 | BOOL isEqual = NO; 45 | if ([object isKindOfClass:[RBSpecFile class]]) { 46 | RBSpecFile* file = (RBSpecFile*)object; 47 | isEqual = [self.url isEqual:file.url] 48 | || [self.url.lastPathComponent isEqualToString:file.url.lastPathComponent]; 49 | isEqual &= [self.fileName isEqualToString:file.fileName]; 50 | } 51 | return isEqual; 52 | } 53 | 54 | #pragma mark - Public Functions 55 | - (void)fetchUrl { 56 | if ([self.url scheme] && ![self.url isFileURL]) { 57 | [self sdl_fetchRemoteURL:self.url]; 58 | } else { 59 | if ([[NSFileManager defaultManager] fileExistsAtPath:self.url.path]) { 60 | [self sdl_fetchURL:self.url]; 61 | } else { 62 | [self sdl_fetchBundleURL:self.url]; 63 | } 64 | } 65 | } 66 | 67 | #pragma mark - Getters 68 | - (NSString*)fileName { 69 | return [self.url lastPathComponent]; 70 | } 71 | 72 | #pragma mark - Private 73 | #pragma mark Helpers 74 | - (void)sdl_fetchBundleURL:(NSURL*)url { 75 | NSString* lastPathComponent = [url lastPathComponent]; 76 | NSURL* bundleURL = [[NSBundle mainBundle] URLForResource:[lastPathComponent stringByDeletingPathExtension] 77 | withExtension:[lastPathComponent pathExtension]]; 78 | [self sdl_fetchURL:bundleURL]; 79 | } 80 | 81 | - (void)sdl_fetchURL:(NSURL*)url { 82 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 83 | NSData* fileData = [NSData dataWithContentsOfURL:url]; 84 | if (fileData) { 85 | _data = fileData; 86 | [self sdl_didFinish]; 87 | } else { 88 | NSString* errorString = [NSString stringWithFormat:@"File not found at %@", url.absoluteString]; 89 | NSError* error = [NSError errorWithDomain:@"com.smartdevicelink.RBSpecFile" 90 | code:404 91 | userInfo:@{NSLocalizedDescriptionKey : errorString}]; 92 | [self sdl_didFinishWithError:error]; 93 | } 94 | }); 95 | } 96 | 97 | - (void)sdl_fetchRemoteURL:(NSURL*)url { 98 | NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration]; 99 | config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; 100 | 101 | NSURLSession* session = [NSURLSession sessionWithConfiguration:config]; 102 | [[session downloadTaskWithURL:self.url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { 103 | if (location) { 104 | NSError* saveError = nil; 105 | NSURL* documentsPath = [NSURL fileURLWithPath:self.documentsPathString]; 106 | NSString* fileName = [NSString stringWithFormat:@"%f-spec.xml", [[NSDate date] timeIntervalSince1970]]; 107 | documentsPath = [documentsPath URLByAppendingPathComponent:fileName]; 108 | if (![[NSFileManager defaultManager] moveItemAtURL:location 109 | toURL:documentsPath 110 | error:&saveError]) { 111 | [self sdl_didFinishWithError:error]; 112 | } else { 113 | [self sdl_didFinish]; 114 | } 115 | } else if (error) { 116 | [self sdl_didFinishWithError:error]; 117 | } 118 | }] resume]; 119 | } 120 | 121 | - (void)sdl_didFinish { 122 | dispatch_async(dispatch_get_main_queue(), ^{ 123 | [self.delegate specFileFetchUrlDidFinish:self]; 124 | }); 125 | } 126 | 127 | - (void)sdl_didFinishWithError:(NSError*)error { 128 | dispatch_async(dispatch_get_main_queue(), ^{ 129 | [self.delegate specFile:self fetchUrlDidFinishWithError:error]; 130 | }); 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBStruct.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBStruct.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBElement.h" 7 | #import "RBParam.h" 8 | 9 | @interface RBStruct : RBElement 10 | 11 | - (void)addParameter:(RBParam*)param; 12 | 13 | @property (nonatomic, readonly) NSArray* parameters; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RPC Builder/Data Models/RBStruct.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBStruct.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBStruct.h" 7 | 8 | @interface RBStruct () 9 | 10 | @property (nonatomic, strong) NSMutableArray* mutableParams; 11 | 12 | @end 13 | 14 | @implementation RBStruct 15 | 16 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary { 17 | if (self = [super initWithDictionary:dictionary]) { 18 | _mutableParams = [NSMutableArray array]; 19 | } 20 | return self; 21 | } 22 | 23 | #pragma mark - Public 24 | - (void)addParameter:(RBParam *)param { 25 | [_mutableParams addObject:param]; 26 | } 27 | 28 | #pragma mark - Getters 29 | - (NSString*)description { 30 | NSMutableString* mutableDescription = [super.description mutableCopy]; 31 | if (self.parameters.count) { 32 | [mutableDescription insertString:[NSString stringWithFormat:@", parameters: %@", self.parameters] 33 | atIndex:mutableDescription.length-1]; 34 | } 35 | return [mutableDescription copy]; 36 | } 37 | 38 | - (NSArray*)parameters { 39 | return [_mutableParams copy]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /RPC Builder/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIcons 10 | 11 | CFBundleIcons~ipad 12 | 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.2.3 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 11 27 | LSRequiresIPhoneOS 28 | 29 | UIBackgroundModes 30 | 31 | external-accessory 32 | 33 | UIFileSharingEnabled 34 | 35 | UILaunchStoryboardName 36 | LaunchScreen 37 | UIMainStoryboardFile 38 | Main 39 | UIRequiredDeviceCapabilities 40 | 41 | armv7 42 | 43 | UISupportedExternalAccessoryProtocols 44 | 45 | com.ford.sync.prot0 46 | com.smartdevicelink.prot0 47 | com.smartdevicelink.prot1 48 | com.smartdevicelink.prot2 49 | com.smartdevicelink.prot3 50 | com.smartdevicelink.prot4 51 | com.smartdevicelink.prot5 52 | com.smartdevicelink.prot6 53 | com.smartdevicelink.prot7 54 | com.smartdevicelink.prot8 55 | com.smartdevicelink.prot9 56 | com.smartdevicelink.prot10 57 | com.smartdevicelink.prot11 58 | com.smartdevicelink.prot12 59 | com.smartdevicelink.prot13 60 | com.smartdevicelink.prot14 61 | com.smartdevicelink.prot15 62 | com.smartdevicelink.prot16 63 | com.smartdevicelink.prot17 64 | com.smartdevicelink.prot18 65 | com.smartdevicelink.prot19 66 | com.smartdevicelink.prot20 67 | com.smartdevicelink.prot21 68 | com.smartdevicelink.prot22 69 | com.smartdevicelink.prot23 70 | com.smartdevicelink.prot24 71 | com.smartdevicelink.prot25 72 | com.smartdevicelink.prot26 73 | com.smartdevicelink.prot27 74 | com.smartdevicelink.prot28 75 | com.smartdevicelink.prot29 76 | 77 | UISupportedInterfaceOrientations 78 | 79 | UIInterfaceOrientationPortrait 80 | 81 | UISupportedInterfaceOrientations~ipad 82 | 83 | UIInterfaceOrientationPortrait 84 | UIInterfaceOrientationPortraitUpsideDown 85 | UIInterfaceOrientationLandscapeLeft 86 | UIInterfaceOrientationLandscapeRight 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /RPC Builder/SmartDeviceLink/RBSDLConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBConfiguration.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | extern NSString* const SDLConnectionTypeStringiAP; 9 | extern NSString* const SDLConnectionTypeStringTCP; 10 | 11 | extern NSString* const SDLAppTypeStringMedia; 12 | extern NSString* const SDLAppTypeStringNonMedia; 13 | extern NSString* const SDLAppTypeStringNavigation; 14 | 15 | typedef NS_ENUM(NSUInteger, SDLConnectionType) { 16 | SDLConnectionTypeiAP, 17 | SDLConnectionTypeTCP, 18 | SDLConnectionTypeUnknown 19 | }; 20 | 21 | typedef NS_ENUM(NSUInteger, SDLAppType) { 22 | SDLAppTypeMedia = 0, 23 | SDLAppTypeNonMedia, 24 | SDLAppTypeNavigation, 25 | SDLAppTypeUnknown 26 | }; 27 | 28 | @interface RBSDLConfiguration : NSObject 29 | 30 | /* 31 | * Returns all available connection type's respective string values. 32 | */ 33 | + (NSArray*)connectionTypeStrings; 34 | 35 | /* 36 | * Returns all available app type's respective string values. 37 | */ 38 | + (NSArray*)appTypeStrings; 39 | 40 | /* 41 | * Default configuration. Uses a connectionType of iAP. 42 | */ 43 | + (instancetype)defaultConfiguration; 44 | 45 | /* 46 | * Uses a connectionType of TCPSpecified with using specified ip address and port. 47 | */ 48 | + (instancetype)tcpConfiguration:(NSString*)ipAddress port:(NSString*)port; 49 | 50 | @property (nonatomic, readonly) SDLConnectionType connectionType; 51 | @property (nonatomic, readonly) NSString* connectionTypeString; 52 | @property (nonatomic, readonly) NSString* ipAddress; 53 | @property (nonatomic, readonly) NSString* port; 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /RPC Builder/SmartDeviceLink/RBSDLConfiguration.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBConfiguration.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSDLConfiguration.h" 7 | 8 | NSString* const SDLConnectionTypeStringiAP = @"iAP"; 9 | NSString* const SDLConnectionTypeStringTCP = @"TCP"; 10 | 11 | NSString* const SDLAppTypeStringMedia = @"Media"; 12 | NSString* const SDLAppTypeStringNonMedia = @"Non-Media"; 13 | NSString* const SDLAppTypeStringNavigation = @"Navigation"; 14 | 15 | @implementation RBSDLConfiguration 16 | 17 | - (instancetype)init { 18 | if (self = [super init]) { 19 | _connectionType = SDLConnectionTypeiAP; 20 | _ipAddress = nil; 21 | _port = nil; 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - Class Constructors 27 | + (instancetype)defaultConfiguration { 28 | return [[RBSDLConfiguration alloc] init]; 29 | } 30 | 31 | + (instancetype)tcpConfiguration:(NSString *)ipAddress port:(NSString *)port { 32 | RBSDLConfiguration* config = [self defaultConfiguration]; 33 | config->_connectionType = SDLConnectionTypeTCP; 34 | config->_ipAddress = ipAddress; 35 | config->_port = port; 36 | return config; 37 | } 38 | 39 | #pragma mark - Getters 40 | + (NSArray*)appTypeStrings { 41 | static NSArray* appTypeStrings = nil; 42 | static dispatch_once_t onceToken; 43 | dispatch_once(&onceToken, ^{ 44 | if (!appTypeStrings) { 45 | appTypeStrings = @[SDLAppTypeStringMedia, 46 | SDLAppTypeStringNonMedia, 47 | SDLAppTypeStringNavigation 48 | ]; 49 | } 50 | }); 51 | return appTypeStrings; 52 | } 53 | 54 | - (NSString*)connectionTypeString { 55 | switch (self.connectionType) { 56 | case SDLConnectionTypeiAP: 57 | return SDLConnectionTypeStringiAP; 58 | break; 59 | case SDLConnectionTypeTCP: 60 | return SDLConnectionTypeStringTCP; 61 | break; 62 | default: 63 | return nil; 64 | break; 65 | } 66 | } 67 | 68 | + (NSArray*)connectionTypeStrings { 69 | static NSArray* connectionTypeStrings = nil; 70 | static dispatch_once_t onceToken; 71 | dispatch_once(&onceToken, ^{ 72 | if (!connectionTypeStrings) { 73 | connectionTypeStrings = @[SDLConnectionTypeStringiAP, 74 | SDLConnectionTypeStringTCP]; 75 | } 76 | }); 77 | return connectionTypeStrings; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /RPC Builder/SmartDeviceLink/RBSDLManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBManager.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | #import "RBSDLConfiguration.h" 9 | 10 | @class SDLProxy; 11 | @class SDLRPCRequest; 12 | 13 | extern NSString* const SDLManagerRegisterAppInterfaceResponseNotification; 14 | 15 | extern NSString* const SDLManagerConnectedKeyPath; 16 | extern void* SDLManagerConnectedContext; 17 | 18 | @interface RBSDLManager : NSObject 19 | 20 | @property (nonatomic, readonly) SDLProxy* proxy; 21 | 22 | @property (nonatomic, readonly, getter=isConnected) BOOL connected; 23 | 24 | @property (nonatomic, strong) NSDictionary* registerAppDictionary; 25 | 26 | + (instancetype)sharedManager; 27 | 28 | // Creates generic SDLRPCRequest for a given dictionary. 29 | - (SDLRPCRequest*)requestForDictionary:(NSDictionary*)requestDictionary withBulkData:(NSData*)bulkData; 30 | 31 | // Creates a specific SDLRPCRequest subtype for a given dictionary. 32 | - (id)requestOfClass:(Class)classType forDictionary:(NSDictionary*)requestDictionary withBulkData:(NSData*)bulkData; 33 | 34 | - (BOOL)connectWithConfiguration:(RBSDLConfiguration*)configuration; 35 | - (void)disconnect; 36 | 37 | - (void)sendRequestDictionary:(NSDictionary*)requestDictionary bulkData:(NSData*)bulkData; 38 | 39 | - (NSNumber*)sendRequest:(SDLRPCRequest*)request; 40 | 41 | - (void)presentSettingsViewController; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /RPC Builder/SmartDeviceLink/RBSDLManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBManager.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSDLManager.h" 7 | #import "SmartDeviceLink.h" 8 | 9 | #import "RBSettingsViewController.h" 10 | #import "RBAppRegistrationViewController.h" 11 | 12 | NSString* const SDLManagerRegisterAppInterfaceResponseNotification = @"SDLManagerRegisterAppInterfaceResponseNotification"; 13 | 14 | NSString* const SDLManagerConnectedKeyPath = @"isConnected"; 15 | void* SDLManagerConnectedContext = &SDLManagerConnectedContext; 16 | 17 | static NSString* const AppIconFileName = @"SDLAppIcon"; 18 | 19 | static NSString* const SDLRequestKey = @"request"; 20 | 21 | @interface RBSDLManager () 22 | 23 | @property (nonatomic, strong) RBSDLConfiguration* configuration; 24 | 25 | @property (nonatomic) NSUInteger correlationID; 26 | @property (nonatomic, readonly) NSNumber* nextCorrelationID; 27 | 28 | @end 29 | 30 | @implementation RBSDLManager 31 | 32 | + (instancetype)sharedManager { 33 | static RBSDLManager* sharedManager = nil; 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | sharedManager = [[RBSDLManager alloc] init]; 37 | }); 38 | 39 | return sharedManager; 40 | } 41 | 42 | #pragma mark - Public 43 | - (BOOL)connectWithConfiguration:(RBSDLConfiguration *)configuration { 44 | if (!configuration) { 45 | NSLog(@"No specified configuration. Cannot start proxy."); 46 | return NO; 47 | } 48 | if (self.isConnected || _proxy) { 49 | [self disconnect]; 50 | } 51 | _configuration = configuration; 52 | switch (configuration.connectionType) { 53 | case SDLConnectionTypeiAP: 54 | _proxy = [SDLProxyFactory buildSDLProxyWithListener:self]; 55 | break; 56 | case SDLConnectionTypeTCP: 57 | _proxy = [SDLProxyFactory buildSDLProxyWithListener:self 58 | tcpIPAddress:configuration.ipAddress 59 | tcpPort:configuration.port]; 60 | break; 61 | case SDLConnectionTypeUnknown: 62 | default: 63 | NSLog(@"Unknown proxy configuration."); 64 | return NO; 65 | break; 66 | } 67 | return YES; 68 | } 69 | 70 | - (void)disconnect { 71 | _configuration = nil; 72 | [self sdl_stopProxy]; 73 | } 74 | 75 | - (SDLRPCRequest*)requestForDictionary:(NSDictionary *)requestDictionary withBulkData:(NSData *)bulkData { 76 | return [self requestOfClass:[SDLRPCRequest class] 77 | forDictionary:requestDictionary 78 | withBulkData:bulkData]; 79 | } 80 | 81 | - (id)requestOfClass:(Class)classType forDictionary:(NSDictionary*)requestDictionary withBulkData:(NSData*)bulkData { 82 | NSMutableDictionary* mutableRequestDictionary = [@{SDLRequestKey : requestDictionary} mutableCopy]; 83 | if (![classType isSubclassOfClass:[SDLRPCRequest class]]) { 84 | NSLog(@"Attempting to convert dictionary for %@ that is not a subclass of %@", NSStringFromClass(classType), NSStringFromClass(SDLRPCRequest.class)); 85 | return nil; 86 | } 87 | id request = [[classType alloc] initWithDictionary:mutableRequestDictionary]; 88 | [request setBulkData:bulkData]; 89 | return request; 90 | } 91 | 92 | - (void)sendRequestDictionary:(NSDictionary *)requestDictionary bulkData:(NSData *)bulkData { 93 | [self sendRequest:[self requestForDictionary:requestDictionary 94 | withBulkData:bulkData]]; 95 | } 96 | 97 | - (NSNumber*)sendRequest:(SDLRPCRequest *)request { 98 | if (!self.isConnected) { 99 | return nil; 100 | } 101 | request.correlationID = self.nextCorrelationID; 102 | [_proxy sendRPC:request]; 103 | return request.correlationID; 104 | } 105 | 106 | - (void)presentSettingsViewController { 107 | UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Main" 108 | bundle:nil]; 109 | RBSettingsViewController* settingsViewController = [storyboard instantiateViewControllerWithIdentifier:@"RBSettingsViewController"]; 110 | UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; 111 | 112 | UIViewController* rootViewController = [self sdl_getTopMostViewController:[UIApplication sharedApplication].keyWindow.rootViewController]; 113 | 114 | if (![rootViewController isKindOfClass:[RBAppRegistrationViewController class]]) { 115 | // HAX: http://stackoverflow.com/questions/1922517/how-does-performselectorwithobjectafterdelay-work 116 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 117 | [rootViewController presentViewController:navigationController 118 | animated:YES 119 | completion:nil]; 120 | }); 121 | } 122 | } 123 | 124 | #pragma mark Getters 125 | - (NSNumber*)nextCorrelationID { 126 | return @(++_correlationID); 127 | } 128 | 129 | #pragma mark - Delegates 130 | #pragma mark SDLProxyListener 131 | - (void)onOnDriverDistraction:(SDLOnDriverDistraction *)notification { } 132 | 133 | - (void)onOnHMIStatus:(SDLOnHMIStatus *)notification { } 134 | 135 | - (void)onProxyClosed { 136 | [self sdl_stopProxy]; 137 | } 138 | 139 | - (void)onProxyOpened { 140 | [self sdl_updatedIsConnected:YES]; 141 | [UIApplication sharedApplication].idleTimerDisabled = YES; 142 | if (self.registerAppDictionary) { 143 | [self sendRequestDictionary:self.registerAppDictionary 144 | bulkData:nil]; 145 | } 146 | } 147 | 148 | - (void)onRegisterAppInterfaceResponse:(SDLRegisterAppInterfaceResponse *)response { 149 | if (![response.success boolValue]) { 150 | [self disconnect]; 151 | } 152 | [[NSNotificationCenter defaultCenter] postNotificationName:SDLManagerRegisterAppInterfaceResponseNotification 153 | object:response]; 154 | } 155 | 156 | #pragma mark - Private 157 | - (void)sdl_stopProxy { 158 | [self sdl_updatedIsConnected:NO]; 159 | [UIApplication sharedApplication].idleTimerDisabled = NO; 160 | [_proxy dispose]; 161 | _proxy = nil; 162 | } 163 | 164 | - (void)sdl_updatedIsConnected:(BOOL)connected { 165 | [self willChangeValueForKey:@"isConnected"]; 166 | _connected = connected; 167 | [self didChangeValueForKey:@"isConnected"]; 168 | 169 | if (![[RBSDLManager sharedManager] isConnected]) { 170 | [self presentSettingsViewController]; 171 | } 172 | } 173 | 174 | - (UIViewController*)sdl_getTopMostViewController:(UIViewController*)viewController { 175 | if ([viewController presentedViewController]) { 176 | return [self sdl_getTopMostViewController:[viewController presentedViewController]]; 177 | } else if ([viewController isKindOfClass:[UINavigationController class]]) { 178 | return [[(UINavigationController*)viewController viewControllers] lastObject]; 179 | } else { 180 | return viewController; 181 | } 182 | } 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSData+Chunks.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Chunks.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/31/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSData (Chunks) 12 | 13 | - (NSArray*)dataChunksOfSize:(NSUInteger)size; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSData+Chunks.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Chunks.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/31/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "NSData+Chunks.h" 10 | 11 | @implementation NSData (Chunks) 12 | 13 | - (NSArray*)dataChunksOfSize:(NSUInteger)size { 14 | NSUInteger chunkCount = MAX(1, ceil(self.length / size)); 15 | 16 | NSMutableArray* chunks = [NSMutableArray arrayWithCapacity:chunkCount]; 17 | 18 | NSUInteger currentIndex = 0; 19 | 20 | while (currentIndex < self.length) { 21 | NSUInteger dataLength = 0; 22 | if (currentIndex + size < self.length) { 23 | dataLength = size; 24 | } else { 25 | dataLength = self.length - currentIndex; 26 | } 27 | 28 | NSRange dataRange = NSMakeRange(currentIndex, dataLength); 29 | NSData* chunk = [self subdataWithRange:dataRange]; 30 | 31 | [chunks addObject:chunk]; 32 | 33 | currentIndex += dataLength; 34 | } 35 | 36 | return [chunks copy]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSFileWrapper+Extensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileWrapper+Extensions.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface NSFileWrapper (Extensions) 9 | 10 | @property (nonatomic, readonly) NSUInteger fileSize; 11 | @property (nonatomic, readonly) NSString* fileSizeString; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSFileWrapper+Extensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileWrapper+Extensions.m 3 | // RPC Builder 4 | // 5 | 6 | #import "NSFileWrapper+Extensions.h" 7 | 8 | @implementation NSFileWrapper (Extensions) 9 | 10 | - (NSUInteger)fileSize { 11 | return [self.fileAttributes[NSFileSize] unsignedIntegerValue]; 12 | } 13 | 14 | - (NSString*)fileSizeString { 15 | return [self.byteFormatter stringFromByteCount:self.fileSize]; 16 | } 17 | 18 | - (NSByteCountFormatter*)byteFormatter { 19 | static NSByteCountFormatter* byteFormatter = nil; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | if (!byteFormatter) { 23 | byteFormatter = [[NSByteCountFormatter alloc] init]; 24 | byteFormatter.countStyle = NSByteCountFormatterCountStyleBinary; 25 | } 26 | }); 27 | return byteFormatter; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSLayoutConstraint+CopyWithZone.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSLayoutConstraint+CopyWithZone.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface NSLayoutConstraint (CopyWithZone) 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSLayoutConstraint+CopyWithZone.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSLayoutConstraint+CopyWithZone.m 3 | // RPC Builder 4 | // 5 | 6 | #import "NSLayoutConstraint+CopyWithZone.h" 7 | 8 | @implementation NSLayoutConstraint (CopyWithZone) 9 | 10 | - (instancetype)copyWithZone:(NSZone *)zone { 11 | NSLayoutConstraint* constraint = [NSLayoutConstraint constraintWithItem:self.firstItem 12 | attribute:self.firstAttribute 13 | relatedBy:self.relation 14 | toItem:self.secondItem 15 | attribute:self.secondAttribute 16 | multiplier:self.multiplier 17 | constant:self.constant]; 18 | return constraint; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSString+Regex.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Regex.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 6/7/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Regex) 12 | 13 | - (NSString*)firstStringMatchUsingRegex:(NSRegularExpression*)regex; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/NSString+Regex.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Regex.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 6/7/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "NSString+Regex.h" 10 | 11 | @implementation NSString (Regex) 12 | 13 | - (NSString*)firstStringMatchUsingRegex:(NSRegularExpression*)regex { 14 | if (!self.length) { 15 | return nil; 16 | } 17 | NSTextCheckingResult* match = [regex firstMatchInString:self 18 | options:NSMatchingReportCompletion 19 | range:NSMakeRange(0, self.length)]; 20 | 21 | NSRange matchRange = ([match numberOfRanges] > 1) ? [match rangeAtIndex:1] : [match range]; 22 | 23 | return [self substringWithRange:matchRange]; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIAlertAction+Minimal.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertAction+Minimal.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface UIAlertAction (Minimal) 9 | 10 | + (instancetype)simpleOkAction; 11 | 12 | + (instancetype)simpleCancelAction; 13 | 14 | + (instancetype)defaultActionWithTitle:(NSString*)title handler:(void (^)(UIAlertAction* action))handler; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIAlertAction+Minimal.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertAction+Minimal.m 3 | // RPC Builder 4 | // 5 | 6 | #import "UIAlertAction+Minimal.h" 7 | 8 | @implementation UIAlertAction (Minimal) 9 | 10 | + (instancetype)simpleOkAction { 11 | return [self defaultActionWithTitle:@"Ok" 12 | handler:nil]; 13 | } 14 | 15 | + (instancetype)simpleCancelAction { 16 | return [UIAlertAction actionWithTitle:@"Cancel" 17 | style:UIAlertActionStyleCancel 18 | handler:nil]; 19 | } 20 | 21 | 22 | + (instancetype)defaultActionWithTitle:(NSString*)title handler:(void (^)(UIAlertAction* action))handler { 23 | return [UIAlertAction actionWithTitle:title 24 | style:UIAlertActionStyleDefault 25 | handler:handler]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIAlertController+Minimal.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertController+Minimal.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import "UIAlertAction+Minimal.h" 8 | 9 | @interface UIAlertController (Minimal) 10 | 11 | + (instancetype)simpleAlertWithTitle:(NSString*)title message:(NSString*)message; 12 | 13 | + (instancetype)simpleErrorAlertWithMessage:(NSString*)message; 14 | 15 | + (instancetype)alertWithTitle:(NSString*)title message:(NSString*)message action:(UIAlertAction*)action; 16 | 17 | + (instancetype)actionSheetWithTitle:(NSString*)title message:(NSString*)message; 18 | 19 | - (void)addDefaultActionWithTitle:(NSString*)title handler:(void (^)(UIAlertAction* action))handler; 20 | - (void)addDestructiveActionWithTitle:(NSString*)title handler:(void (^)(UIAlertAction* action))handler; 21 | - (void)addCancelAction; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIAlertController+Minimal.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertController+Minimal.m 3 | // RPC Builder 4 | // 5 | 6 | #import "UIAlertController+Minimal.h" 7 | 8 | @implementation UIAlertController (Minimal) 9 | 10 | + (instancetype)simpleAlertWithTitle:(NSString*)title message:(NSString*)message { 11 | return [self alertWithTitle:title message:message action:[UIAlertAction simpleOkAction]]; 12 | } 13 | 14 | + (instancetype)simpleErrorAlertWithMessage:(NSString*)message { 15 | return [self simpleAlertWithTitle:@"Error" message:message]; 16 | } 17 | 18 | + (instancetype)alertWithTitle:(NSString*)title message:(NSString*)message action:(UIAlertAction*)action { 19 | UIAlertController* alertController = [self alertControllerWithTitle:title 20 | message:message 21 | preferredStyle:UIAlertControllerStyleAlert]; 22 | if (action) { 23 | [alertController addAction:action]; 24 | } 25 | return alertController; 26 | } 27 | 28 | + (instancetype)actionSheetWithTitle:(NSString*)title message:(NSString*)message { 29 | UIAlertController* alertController = [self alertControllerWithTitle:title 30 | message:message 31 | preferredStyle:UIAlertControllerStyleActionSheet]; 32 | return alertController; 33 | } 34 | 35 | - (void)addDefaultActionWithTitle:(NSString *)title handler:(void (^)(UIAlertAction *))handler { 36 | [self sdl_addActionWithTitle:title 37 | style:UIAlertActionStyleDefault 38 | handler:handler]; 39 | } 40 | 41 | - (void)addDestructiveActionWithTitle:(NSString *)title handler:(void (^)(UIAlertAction *))handler { 42 | [self sdl_addActionWithTitle:title 43 | style:UIAlertActionStyleDestructive 44 | handler:handler]; 45 | } 46 | 47 | - (void)addCancelAction { 48 | [self addAction:[UIAlertAction simpleCancelAction]]; 49 | } 50 | 51 | #pragma mark - Private 52 | - (void)sdl_addActionWithTitle:(NSString*)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *))handler { 53 | [self addAction:[UIAlertAction actionWithTitle:title 54 | style:style 55 | handler:handler]]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIColor+Util.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Util.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 6/7/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (Util) 12 | 13 | // RBLogInfo's Type 14 | + (UIColor*)notificationColor; 15 | + (UIColor*)requestColor; 16 | + (UIColor*)responseColor; 17 | + (UIColor*)systemColor; 18 | 19 | // RBLogInfo's Response 20 | + (UIColor*)successColor; 21 | + (UIColor*)warningColor; 22 | + (UIColor*)errorColor; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIColor+Util.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Util.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 6/7/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "UIColor+Util.h" 10 | 11 | @implementation UIColor (Util) 12 | 13 | #pragma mark - RBLogInfo's Type 14 | + (UIColor*)notificationColor { 15 | static UIColor* notificationColor = nil; 16 | if (!notificationColor) { 17 | notificationColor = [UIColor colorWithRed:241/255.0 18 | green:196/255.0 19 | blue:15/255.0 20 | alpha:0.5]; 21 | } 22 | return notificationColor; 23 | } 24 | 25 | + (UIColor*)responseColor { 26 | static UIColor* responseColor = nil; 27 | if (!responseColor) { 28 | responseColor = [UIColor colorWithRed:46/255.0 29 | green:204/255.0 30 | blue:113/255.0 31 | alpha:0.5]; 32 | } 33 | return responseColor; 34 | } 35 | 36 | + (UIColor*)requestColor { 37 | static UIColor* requestColor = nil; 38 | if (!requestColor) { 39 | requestColor = [UIColor colorWithRed:52/255.0 40 | green:152/255.0 41 | blue:219/255.0 42 | alpha:0.5]; 43 | } 44 | return requestColor; 45 | } 46 | 47 | + (UIColor*)systemColor { 48 | static UIColor* systemColor = nil; 49 | if (!systemColor) { 50 | systemColor = [UIColor colorWithRed:236/255.0 51 | green:240/255.0 52 | blue:241/255.0 53 | alpha:0.5]; 54 | } 55 | return systemColor; 56 | } 57 | 58 | #pragma mark - RBLogInfo's Response 59 | + (UIColor*)successColor { 60 | static UIColor* successColor = nil; 61 | if (!successColor) { 62 | successColor = [UIColor colorWithRed:46/255.0 63 | green:204/255.0 64 | blue:113/255.0 65 | alpha:0.5]; 66 | } 67 | return successColor; 68 | } 69 | 70 | + (UIColor*)warningColor { 71 | static UIColor* warningColor = nil; 72 | if (!warningColor) { 73 | warningColor = [UIColor colorWithRed:241/255.0 74 | green:196/255.0 75 | blue:15/255.0 76 | alpha:0.5]; 77 | 78 | } 79 | return warningColor; 80 | } 81 | 82 | + (UIColor*)errorColor { 83 | static UIColor* errorColor = nil; 84 | if (!errorColor) { 85 | errorColor = [UIColor colorWithRed:192/255.0 86 | green:57/255.0 87 | blue:43/255.0 88 | alpha:0.5]; 89 | } 90 | return errorColor; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIView+Util.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Resize.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import "RBView.h" 8 | #import "RBDeviceInformation.h" 9 | 10 | @interface UIView (Util) 11 | 12 | - (void)resizeToFit:(CGSize)size; 13 | 14 | - (void)rightAlignmentWithReferenceRect:(CGRect)referenceRect; 15 | 16 | - (void)bottomAlignmentWithReferenceRect:(CGRect)referenceRect; 17 | 18 | - (void)copyParentConstraintsToView:(UIView*)view; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/Categories/UIView+Util.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Resize.m 3 | // RPC Builder 4 | // 5 | 6 | #import "UIView+Util.h" 7 | 8 | @implementation UIView (Util) 9 | 10 | - (void)resizeToFit:(CGSize)size { 11 | CGSize sizeToFit = [self sizeThatFits:size]; 12 | 13 | CGFloat maxHeight = sizeToFit.height; 14 | CGFloat maxWidth = sizeToFit.width; 15 | 16 | if (self.subviews.count) { 17 | for (UIView* subview in self.subviews) { 18 | maxHeight = MAX(maxHeight, CGRectGetMaxY(subview.frame)); 19 | maxWidth = MAX(maxWidth, CGRectGetMaxX(subview.frame)); 20 | } 21 | } 22 | 23 | if (maxWidth > size.width) { 24 | maxWidth = size.width; 25 | } 26 | 27 | CGRect sizeRect = self.frame; 28 | sizeRect.size.width = maxWidth; 29 | sizeRect.size.height = maxHeight; 30 | self.frame = sizeRect; 31 | } 32 | 33 | - (void)rightAlignmentWithReferenceRect:(CGRect)referenceRect { 34 | [self sizeToFit]; 35 | CGFloat width = [RBDeviceInformation deviceWidth] - CGRectGetWidth(referenceRect) - (kViewSpacing * 3.0); 36 | CGRect adjustedFrame = CGRectMake(CGRectGetMaxX(referenceRect) + kViewSpacing, 37 | CGRectGetMinY(referenceRect), 38 | width, 39 | MAX(kMinViewHeight, CGRectGetHeight(self.bounds))); 40 | self.frame = adjustedFrame; 41 | 42 | // This will happen only when a UIView's width cannot grow (i.e. UISwitch) 43 | if (CGRectGetWidth(self.bounds) < width) { 44 | width = CGRectGetWidth(self.bounds); 45 | adjustedFrame.origin.x = [RBDeviceInformation deviceWidth] - width - (kViewSpacing * 2.0); 46 | adjustedFrame.size.width = width; 47 | self.frame = adjustedFrame; 48 | } 49 | } 50 | 51 | - (void)bottomAlignmentWithReferenceRect:(CGRect)referenceRect { 52 | [self sizeToFit]; 53 | CGFloat width = [RBDeviceInformation deviceWidth] - (kViewSpacing * 2.0); 54 | CGRect adjustedFrame = CGRectMake(CGRectGetMinX(referenceRect), 55 | CGRectGetMaxY(referenceRect) + kViewSpacing, 56 | width, 57 | MAX(kMinViewHeight, CGRectGetHeight(self.bounds))); 58 | self.frame = adjustedFrame; 59 | } 60 | 61 | - (void)copyParentConstraintsToView:(UIView*)view { 62 | view.translatesAutoresizingMaskIntoConstraints = NO; 63 | 64 | NSMutableArray* removeConstraints = [NSMutableArray array]; 65 | NSMutableArray* addConstraints = [NSMutableArray array]; 66 | 67 | for (NSLayoutConstraint* constraint in self.superview.constraints) { 68 | if (constraint.firstItem == self || constraint.secondItem == self) { 69 | id firstItem = nil; 70 | id secondItem = nil; 71 | if (constraint.firstItem != nil) { 72 | firstItem = (constraint.firstItem == self) ? view : constraint.firstItem; 73 | } 74 | if (constraint.secondItem != nil) { 75 | secondItem = (constraint.secondItem == self) ? view : constraint.secondItem; 76 | } 77 | 78 | NSLayoutConstraint* newConstraint = [NSLayoutConstraint constraintWithItem:firstItem 79 | attribute:constraint.firstAttribute 80 | relatedBy:constraint.relation 81 | toItem:secondItem 82 | attribute:constraint.secondAttribute 83 | multiplier:constraint.multiplier 84 | constant:constraint.constant]; 85 | newConstraint.priority = constraint.priority; 86 | newConstraint.active = constraint.isActive; 87 | 88 | [addConstraints addObject:newConstraint]; 89 | [removeConstraints addObject:constraint]; 90 | } 91 | } 92 | 93 | [self.superview removeConstraints:removeConstraints]; 94 | [self.superview addConstraints:addConstraints]; 95 | 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/NSObject+Swizzle.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Swizzle.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 9/15/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "SmartDeviceLink.h" 10 | 11 | @interface NSObject (Swizzle) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/NSObject+Swizzle.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Swizzle.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 9/15/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Swizzle.h" 10 | 11 | #import 12 | #import "RBParser.h" 13 | 14 | @implementation NSObject (Swizzle) 15 | 16 | + (void)load { 17 | static dispatch_once_t onceToken; 18 | dispatch_once(&onceToken, ^{ 19 | #pragma clang diagnostic push 20 | #pragma clang diagnostic ignored "-Wundeclared-selector" 21 | swizzleForClass(@"SDLFunctionID", @selector(getFunctionID:), @selector(xxx_getFunctionID:)); 22 | swizzleForClass(@"SDLFunctionID", @selector(getFunctionName:), @selector(xxx_getFunctionName:)); 23 | #pragma clang diagnostic pop 24 | }); 25 | } 26 | 27 | - (NSNumber*)xxx_getFunctionID:(NSString *)functionName { 28 | NSNumber* functionID = nil; 29 | for (RBFunction* function in [[RBParser sharedParser] functions]) { 30 | if ([function.name isEqualToString:functionName]) { 31 | NSString* functionIDName = function.functionID; 32 | for (RBElement* element in [[RBParser sharedParser] elements]) { 33 | if ([element.name isEqualToString:functionIDName]) { 34 | functionID = [[self numberFormatter] numberFromString:element.properties[@"value"]]; 35 | break; 36 | } 37 | } 38 | 39 | if (functionID) { 40 | break; 41 | } 42 | } 43 | } 44 | return functionID; 45 | } 46 | 47 | - (NSString*)xxx_getFunctionName:(int)functionID { 48 | NSString* functionName = nil; 49 | for (RBElement* element in [[RBParser sharedParser] elements]) { 50 | if (element.properties.count == 0) { 51 | continue; 52 | } 53 | NSString* elementValue = element.properties[@"value"]; 54 | if ([elementValue isEqualToString:[NSString stringWithFormat:@"%i", functionID]]) { 55 | for (RBFunction* function in [[RBParser sharedParser] functions]) { 56 | if ([function.functionID isEqualToString:element.name]) { 57 | functionName = function.name; 58 | break; 59 | } 60 | } 61 | if (functionName) { 62 | break; 63 | } 64 | } 65 | } 66 | return functionName; 67 | } 68 | 69 | 70 | #pragma mark - Helpers 71 | BOOL swizzleForClass(NSString* className, SEL methodName, SEL swizzleMethodName) { 72 | Class class = NSClassFromString(className); 73 | 74 | if (!class) { 75 | return NO; 76 | } 77 | 78 | SEL originalSelector = methodName; 79 | SEL swizzledSelector = swizzleMethodName; 80 | 81 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 82 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 83 | 84 | BOOL didAddMethod = 85 | class_addMethod(class, 86 | originalSelector, 87 | method_getImplementation(swizzledMethod), 88 | method_getTypeEncoding(swizzledMethod)); 89 | 90 | if (didAddMethod) { 91 | class_replaceMethod(class, 92 | swizzledSelector, 93 | method_getImplementation(originalMethod), 94 | method_getTypeEncoding(originalMethod)); 95 | } else { 96 | method_exchangeImplementations(originalMethod, swizzledMethod); 97 | } 98 | 99 | return YES; 100 | } 101 | 102 | 103 | - (NSNumberFormatter*)numberFormatter { 104 | static NSNumberFormatter* numberFormatter = nil; 105 | if (!numberFormatter) { 106 | numberFormatter = [[NSNumberFormatter alloc] init]; 107 | numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; 108 | } 109 | return numberFormatter; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/RBCamera.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBCamera.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 4/3/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class RBCamera; 13 | 14 | @protocol RBCameraDelegate 15 | 16 | - (void)camera:(RBCamera*)camera hasImageBufferAvailable:(CVImageBufferRef)imageBuffer; 17 | - (void)camera:(RBCamera*)camera didReceiveError:(NSError*)error; 18 | 19 | @end 20 | 21 | @interface RBCamera : NSObject 22 | 23 | - (instancetype)initWithDelegate:(id)delegate; 24 | 25 | - (void)startCapture; 26 | - (void)stopCapture; 27 | 28 | @property (weak) id delegate; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/RBCamera.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBCamera.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 4/3/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBCamera.h" 10 | #import "RBSettingsManager.h" 11 | 12 | @interface RBCamera () 13 | 14 | @property (nonatomic, strong) AVCaptureSession* captureSession; 15 | 16 | @end 17 | 18 | @implementation RBCamera 19 | 20 | - (instancetype)initWithDelegate:(id)delegate { 21 | if (self = [super init]) { 22 | self.delegate = delegate; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)startCapture { 28 | [self.captureSession startRunning]; 29 | } 30 | 31 | - (void)stopCapture { 32 | if (self.captureSession.isRunning) { 33 | [self.captureSession stopRunning]; 34 | self.captureSession = nil; 35 | } 36 | } 37 | 38 | #pragma mark - Delegates 39 | #pragma mark AVCaptureVideoDataOutputSampleBuffer 40 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 41 | CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 42 | 43 | if ([self.delegate respondsToSelector:@selector(camera:hasImageBufferAvailable:)]) { 44 | [self.delegate camera:self hasImageBufferAvailable:imageBuffer]; 45 | } 46 | } 47 | 48 | #pragma mark - Getters { 49 | - (AVCaptureSession*)captureSession { 50 | if (!_captureSession) { 51 | AVCaptureSession* captureSession = [[AVCaptureSession alloc] init]; 52 | [captureSession beginConfiguration]; 53 | 54 | captureSession.sessionPreset = AVCaptureSessionPreset640x480; 55 | 56 | AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 57 | 58 | AVCaptureVideoDataOutput * dataOutput = [[AVCaptureVideoDataOutput alloc] init]; 59 | dataOutput.alwaysDiscardsLateVideoFrames = YES; 60 | 61 | // see if we need this 62 | dataOutput.videoSettings = @{ 63 | (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) 64 | }; 65 | 66 | // can we move this somewhere else? 67 | [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 68 | 69 | if ([captureSession canAddOutput:dataOutput]) { 70 | [captureSession addOutput:dataOutput]; 71 | } 72 | 73 | CMTime minFrameRate = CMTimeMake(1, [RBSettingsManager sharedManager].videoStreamingMinimumFrameRate); 74 | CMTime maxFrameRate = CMTimeMake(1, [RBSettingsManager sharedManager].videoStreamingMaximumFrameRate); 75 | if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_7_0) { 76 | BOOL invalidFrameRate = NO; 77 | NSString* errorMessage = nil; 78 | for (AVFrameRateRange* frameRateRange in [[videoDevice activeFormat] videoSupportedFrameRateRanges]) { 79 | if (frameRateRange.minFrameRate > minFrameRate.timescale) { 80 | errorMessage = [NSString stringWithFormat:@"Min frame rate of %d is invalid. It must be greater than or equal to %.1f.", minFrameRate.timescale, frameRateRange.minFrameRate]; 81 | invalidFrameRate = YES; 82 | } 83 | if (frameRateRange.maxFrameRate < maxFrameRate.timescale) { 84 | errorMessage = [NSString stringWithFormat:@"Max frame rate of %d is invalid. It must be less than or equal to %.1f.", maxFrameRate.timescale, frameRateRange.maxFrameRate]; 85 | invalidFrameRate = YES; 86 | } 87 | if (invalidFrameRate) { 88 | NSError* error = [NSError errorWithDomain:@"com.smartdevicelink.camera" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; 89 | [self sdl_handleError:error]; 90 | [captureSession commitConfiguration]; 91 | return nil; 92 | } 93 | } 94 | [videoDevice lockForConfiguration:nil]; 95 | [videoDevice setActiveVideoMinFrameDuration:maxFrameRate]; 96 | [videoDevice setActiveVideoMaxFrameDuration:minFrameRate]; 97 | [videoDevice unlockForConfiguration]; 98 | } else { 99 | AVCaptureConnection* connection = [dataOutput connectionWithMediaType:AVMediaTypeVideo]; 100 | if (connection.isVideoMinFrameDurationSupported) { 101 | connection.videoMinFrameDuration = maxFrameRate; 102 | } 103 | if (connection.isVideoMaxFrameDurationSupported) { 104 | connection.videoMaxFrameDuration = minFrameRate; 105 | } 106 | if ([captureSession canAddConnection:connection]) { 107 | [captureSession addConnection:connection]; 108 | } 109 | } 110 | 111 | NSError *error; 112 | AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 113 | if (error) { 114 | [self sdl_handleError:error]; 115 | return nil; 116 | } 117 | 118 | if ([captureSession canAddInput:input]) { 119 | [captureSession addInput:input]; 120 | } 121 | 122 | [captureSession commitConfiguration]; 123 | _captureSession = captureSession; 124 | } 125 | 126 | return _captureSession; 127 | } 128 | 129 | #pragma mark - Helpers 130 | - (void)sdl_handleError:(NSError*)error { 131 | if ([self.delegate respondsToSelector:@selector(camera:didReceiveError:)]) { 132 | [self.delegate camera:self didReceiveError:error]; 133 | } 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/RBDeviceInformation.h: -------------------------------------------------------------------------------- 1 | // 2 | // DeviceInformation.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface RBDeviceInformation : NSObject 9 | 10 | + (CGFloat)deviceWidth; 11 | 12 | + (CGSize)maxViewSize; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/RBDeviceInformation.m: -------------------------------------------------------------------------------- 1 | // 2 | // DeviceInformation.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBDeviceInformation.h" 7 | 8 | @implementation RBDeviceInformation 9 | 10 | + (CGFloat)deviceWidth { 11 | return CGRectGetWidth([[[UIApplication sharedApplication] keyWindow] bounds]); 12 | } 13 | 14 | + (CGSize)maxViewSize { 15 | return CGSizeMake([self deviceWidth], CGFLOAT_MAX); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /RPC Builder/Utilities/RBSettingsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBSettingsManager.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import 8 | 9 | #import "RBSDLConfiguration.h" 10 | #import "RBSpecFile.h" 11 | 12 | extern NSString* const RBSettingsManagerSpecFileStatusDidChangeNotification; 13 | extern NSString* const RBSettingsManagerNotificationErrorKey; 14 | 15 | extern NSString* const RBSettingsManagerRPCsAvailableNotification; 16 | 17 | @class SDLLanguage; 18 | 19 | typedef NS_ENUM(NSUInteger, RBSpecFileStatus) { 20 | RBSpecFileStatusNone, 21 | RBSpecFileStatusError, 22 | RBSpecFileStatusSuccess, 23 | }; 24 | 25 | @interface RBSettingsManager : NSObject 26 | 27 | + (instancetype)sharedManager; 28 | 29 | @property (nonatomic, readonly) RBSpecFileStatus specFileStatus; 30 | @property (nonatomic, readonly) NSArray* specXMLs; 31 | @property (nonatomic, strong) RBSpecFile* specFile; 32 | @property (nonatomic, strong) NSString* connectionTypeString; 33 | @property (nonatomic, assign) SDLConnectionType connectionType; 34 | @property (nonatomic, readonly) NSArray* connectionTypes; 35 | @property (nonatomic, strong) NSString* protocolString; 36 | @property (nonatomic, strong) NSString* ipAddress; 37 | @property (nonatomic, strong) NSString* port; 38 | @property (nonatomic, strong) NSString* appName; 39 | @property (nonatomic, strong) NSString* shortAppName; 40 | @property (nonatomic, strong) NSString* appID; 41 | @property (nonatomic, strong) NSString* ttsName; 42 | @property (nonatomic, strong) NSString* ttsTypeString; 43 | @property (nonatomic, strong) NSString* vrSynonymsString; 44 | @property (nonatomic, strong) NSString* appTypeString; 45 | @property (nonatomic, assign) SDLAppType appType; 46 | @property (nonatomic, readonly) NSArray* appTypes; 47 | @property (nonatomic, strong) NSString* vrLanguageString; 48 | @property (nonatomic, strong) NSString* hmiLanguageString; 49 | @property (nonatomic, strong) NSArray* languages; 50 | 51 | @property (nonatomic, strong) NSDictionary* registerAppInterfaceDictionary; 52 | 53 | @property (nonatomic, strong) SDLLanguage* hmiLanguage; 54 | @property (nonatomic, strong) SDLLanguage* vrLanguage; 55 | 56 | @property (nonatomic, readonly) NSArray* availableRPCs; 57 | 58 | // Streaming Module Settings 59 | @property (nonatomic) NSUInteger audioStreamingBufferSize; 60 | @property (nonatomic) NSUInteger videoStreamingBufferSize; 61 | @property (nonatomic) CGFloat videoStreamingMinimumFrameRate; 62 | @property (nonatomic) CGFloat videoStreamingMaximumFrameRate; 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/Modules/Base/RBModuleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBModuleViewController.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBScrollViewController.h" 10 | #import "UIAlertController+Minimal.h" 11 | #import "SmartDeviceLink.h" 12 | #import "RBSettingsManager.h" 13 | #import "RBSDLManager.h" 14 | 15 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending) 16 | 17 | @interface RBModuleViewController : RBScrollViewController 18 | 19 | /* 20 | * Name of the module. Will be shown in list of modules, as well as module's view 21 | * controller. 22 | * 23 | * Required to be Overridden. 24 | */ 25 | + (NSString*)moduleTitle; 26 | 27 | /* 28 | * Description of the module. Will be shown in list of modules if provided. 29 | * 30 | * Required to be Overridden. 31 | */ 32 | + (NSString*)moduleDescription; 33 | 34 | /* 35 | * Name of an image that will represent the module. It will be used in the list of modules. 36 | */ 37 | + (NSString*)moduleImageName; 38 | 39 | /* 40 | * Image used to represent module in a list. 41 | */ 42 | + (UIImage*)moduleImage; 43 | 44 | /* 45 | * Array of all available module class names. 46 | */ 47 | + (NSArray*)moduleClassNames; 48 | 49 | /* 50 | * The minimum required OS version for this module. Defaults to 6.0. 51 | */ 52 | + (NSString*)minimumSupportedVersion; 53 | 54 | /* 55 | * Subclasses' view controller. Will only construct view controller once. 56 | */ 57 | + (RBModuleViewController*)viewController; 58 | 59 | /* 60 | * Proxy given by SDLManager. Logic relating to proxy should be contained with module. 61 | */ 62 | @property (nonatomic, readonly) SDLProxy* proxy; 63 | 64 | /* 65 | * Local reference to SDLManager's singleton. 66 | */ 67 | @property (nonatomic, readonly) RBSDLManager* manager; 68 | 69 | /* 70 | * Local reference to RBSettingsManager's singleton. 71 | */ 72 | @property (nonatomic, readonly) RBSettingsManager* settingsManager; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/Modules/Base/RBModuleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBModuleViewController.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBModuleViewController.h" 10 | 11 | #import "RBStreamingModuleViewController.h" 12 | #import "RBAudioPassThruModuleViewController.h" 13 | 14 | static NSMutableDictionary* moduleImages = nil; 15 | static NSArray* moduleClassNames = nil; 16 | static NSMutableDictionary* moduleViewControllers = nil; 17 | static UIStoryboard* moduleStoryboard = nil; 18 | 19 | @implementation RBModuleViewController 20 | 21 | + (NSString*)moduleTitle { 22 | return @"New Module"; 23 | } 24 | 25 | + (NSString*)moduleDescription { 26 | return nil; 27 | } 28 | 29 | + (NSString*)moduleImageName { 30 | return nil; 31 | } 32 | 33 | + (UIImage*)moduleImage { 34 | if (!self.moduleImageName) { 35 | return nil; 36 | } 37 | if (!moduleImages) { 38 | moduleImages = [NSMutableDictionary dictionary]; 39 | } 40 | UIImage* moduleImage = moduleImages[self.moduleImageName]; 41 | if (!moduleImage) { 42 | moduleImage = [UIImage imageNamed:self.moduleImageName]; 43 | moduleImages[self.moduleImageName] = moduleImage; 44 | } 45 | return moduleImage; 46 | } 47 | 48 | + (NSArray*)moduleClassNames { 49 | if (!moduleClassNames) { 50 | moduleClassNames = @[ 51 | [RBStreamingModuleViewController classString], // Streaming 52 | [RBAudioPassThruModuleViewController classString] // Audio Passthru 53 | ]; 54 | } 55 | return moduleClassNames; 56 | } 57 | 58 | + (NSString*)minimumSupportedVersion { 59 | return @"6.0"; 60 | } 61 | 62 | + (NSString*)classString { 63 | return NSStringFromClass(self.class); 64 | } 65 | 66 | + (RBModuleViewController*)viewController { 67 | if (!moduleViewControllers) { 68 | moduleViewControllers = [NSMutableDictionary dictionary]; 69 | } 70 | NSString* classString = NSStringFromClass(self.class); 71 | RBModuleViewController* viewController = moduleViewControllers[classString]; 72 | if (!viewController) { 73 | if (!moduleStoryboard) { 74 | moduleStoryboard = [UIStoryboard storyboardWithName:@"Modules" 75 | bundle:nil]; 76 | } 77 | @try { 78 | viewController = [moduleStoryboard instantiateViewControllerWithIdentifier:classString]; 79 | moduleViewControllers[classString] = viewController; 80 | } @catch (NSException *exception) { 81 | NSAssert(NO, @"Modules Storyboard does not contain a UIViewController with identifier %@", classString); 82 | } 83 | } 84 | 85 | return viewController; 86 | } 87 | 88 | - (NSString*)title { 89 | return [[self class] moduleTitle]; 90 | } 91 | 92 | - (RBSettingsManager*)settingsManager { 93 | return [RBSettingsManager sharedManager]; 94 | } 95 | 96 | - (RBSDLManager *)manager { 97 | return [RBSDLManager sharedManager]; 98 | } 99 | 100 | - (SDLProxy*)proxy { 101 | return self.manager.proxy; 102 | } 103 | 104 | #pragma mark - Overrides 105 | - (CGFloat)scrollViewBottomOffset { 106 | return CGRectGetHeight(self.tabBarController.tabBar.bounds); 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/Modules/RBAudioPassThruModuleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBAudioPassThruModuleViewController.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 4/18/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBModuleViewController.h" 10 | 11 | @interface RBAudioPassThruModuleViewController : RBModuleViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/Modules/RBStreamingModuleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBStreamingModuleViewController.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBModuleViewController.h" 10 | 11 | @interface RBStreamingModuleViewController : RBModuleViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBAppRegistrationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBAppRegistrationViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBFunctionViewController.h" 7 | 8 | #import "RBSDLConfiguration.h" 9 | 10 | @interface RBAppRegistrationViewController : RBFunctionViewController 11 | 12 | @property (nonatomic, strong) RBSDLConfiguration* sdlConfiguration; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBAppRegistrationViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBAppRegistrationViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBAppRegistrationViewController.h" 7 | 8 | #import "SmartDeviceLink.h" 9 | 10 | #import "UIAlertController+Minimal.h" 11 | 12 | @interface RBAppRegistrationViewController () 13 | 14 | @property (nonatomic, strong, readonly) UIAlertController* raiAlertController; 15 | 16 | @end 17 | 18 | @implementation RBAppRegistrationViewController 19 | 20 | @synthesize raiAlertController = _raiAlertController; 21 | 22 | - (void)viewDidLoad { 23 | 24 | NSDictionary* dict = [self.settingsManager registerAppInterfaceDictionary]; 25 | self.requestDictionary = [dict mutableCopy]; 26 | 27 | [super viewDidLoad]; 28 | 29 | [self.notificationCenter addObserver:self 30 | selector:@selector(registerAppInterfaceResponse:) 31 | name:SDLManagerRegisterAppInterfaceResponseNotification 32 | object:nil]; 33 | } 34 | 35 | #pragma mark - Actions 36 | - (void)sendAction:(id)selector { 37 | [self updateRequestsDictionaryFromSubviews]; 38 | 39 | self.settingsManager.registerAppInterfaceDictionary = self.requestDictionary; 40 | 41 | self.sdlManager.registerAppDictionary = self.requestDictionary; 42 | [self.sdlManager connectWithConfiguration:_sdlConfiguration]; 43 | 44 | [self presentViewController:self.raiAlertController 45 | animated:YES 46 | completion:nil]; 47 | } 48 | 49 | #pragma mark - Notifications 50 | - (void)registerAppInterfaceResponse:(NSNotification*)notification { 51 | SDLRegisterAppInterfaceResponse* response = [notification object]; 52 | if ([response.success boolValue]) { 53 | self.view.userInteractionEnabled = NO; 54 | void(^dismissBlock)(void) = ^ { 55 | [self dismissViewControllerAnimated:YES 56 | completion:nil]; 57 | }; 58 | if (self.presentedViewController == self.raiAlertController) { 59 | [self.raiAlertController dismissViewControllerAnimated:YES 60 | completion:dismissBlock]; 61 | } else { 62 | dismissBlock(); 63 | } 64 | self.view.userInteractionEnabled = YES; 65 | } else { 66 | NSLog(@"Failed to send RAI"); 67 | } 68 | } 69 | 70 | #pragma mark - Private 71 | #pragma mark Getters 72 | - (UIAlertController*)raiAlertController { 73 | if (!_raiAlertController) { 74 | _raiAlertController = [UIAlertController alertWithTitle:@"Connecting…" 75 | message:@"Waiting for Register App Interface Response from SDL Core." 76 | action:nil]; 77 | __typeof__(self) weakSelf = self; 78 | [_raiAlertController addDefaultActionWithTitle:@"Cancel" handler:^(UIAlertAction *action) { 79 | __typeof__(weakSelf) strongSelf = weakSelf; 80 | [strongSelf.sdlManager disconnect]; 81 | }]; 82 | } 83 | return _raiAlertController; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBArrayViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBArrayViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseViewController.h" 7 | 8 | @class RBArrayViewController; 9 | 10 | @protocol RBArrayViewControllerDelegate 11 | 12 | - (void)arrayViewControllerWillDismiss:(RBArrayViewController*)viewController withCount:(NSUInteger)count; 13 | 14 | @end 15 | 16 | @interface RBArrayViewController : RBBaseViewController 17 | 18 | @property (weak) id delegate; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBBaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBBaseViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBScrollViewController.h" 7 | #import "RBParamView.h" 8 | 9 | #import "RBSettingsManager.h" 10 | #import "RBSDLManager.h" 11 | 12 | static const CGFloat kParamViewSpacing = 20.0f; 13 | 14 | @interface RBBaseViewController : RBScrollViewController 15 | 16 | @property (nonatomic, readonly) RBSettingsManager* settingsManager; 17 | @property (nonatomic, readonly) RBSDLManager* sdlManager; 18 | 19 | @property (nonatomic, readonly) UIPickerView* pickerView; 20 | @property (nonatomic, readonly) UIToolbar* doneToolbar; 21 | 22 | @property (nonatomic, strong) NSMutableDictionary* requestDictionary; 23 | @property (nonatomic, strong) NSMutableDictionary* parametersDictionary; 24 | 25 | @property (nonatomic, readonly) NSString* parameterName; 26 | @property (nonatomic, readonly) NSString* paramType; 27 | 28 | @property (nonatomic, strong) NSData* bulkData; 29 | 30 | @property (weak) RBParam* param; 31 | @property (strong) RBStruct* structObj; 32 | @property (strong) RBEnum* enumObj; 33 | 34 | - (void)updateView; 35 | 36 | - (void)updateRequestsDictionaryFromSubviews; 37 | 38 | - (void)loadParameters:(NSArray*)parameters; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBBaseViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 32 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBConsoleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBConsoleViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | #import "SmartDeviceLink.h" 9 | 10 | @interface RBConsoleViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBConsoleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBConsoleViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBConsoleViewController.h" 7 | 8 | #import "UIAlertController+Minimal.h" 9 | 10 | #import "RBLogInfo.h" 11 | 12 | #import "RBLogInfoTableViewCell.h" 13 | 14 | @interface RBConsoleViewController () 15 | 16 | 17 | @property (nonatomic, weak) IBOutlet UITableView* tableView; 18 | @property (nonatomic, strong) UIAlertController* alertController; 19 | 20 | @property (nonatomic, strong) NSMutableArray* messagesArray; 21 | 22 | @end 23 | 24 | @implementation RBConsoleViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | _alertController = [UIAlertController simpleAlertWithTitle:nil 30 | message:nil]; 31 | 32 | _messagesArray = [NSMutableArray arrayWithCapacity:100]; 33 | 34 | [SDLDebugTool addConsole:self]; 35 | 36 | } 37 | 38 | - (void)logInfo:(NSString *)info { 39 | dispatch_async(dispatch_get_main_queue(), ^{ 40 | 41 | [_messagesArray addObject:[RBLogInfo logInfoWithString:info]]; 42 | NSIndexPath* indexPath = [NSIndexPath indexPathForRow:_messagesArray.count - 1 43 | inSection:0]; 44 | UITableViewRowAnimation rowAnimation = UITableViewRowAnimationNone; 45 | BOOL animated = NO; 46 | if (self.tabBarController.selectedViewController == self) { 47 | rowAnimation = UITableViewRowAnimationAutomatic; 48 | animated = YES; 49 | } 50 | 51 | [_tableView insertRowsAtIndexPaths:@[indexPath] 52 | withRowAnimation:rowAnimation]; 53 | [_tableView scrollToRowAtIndexPath:indexPath 54 | atScrollPosition:UITableViewScrollPositionBottom 55 | animated:animated]; 56 | }); 57 | } 58 | 59 | #pragma mark - Getters 60 | 61 | 62 | #pragma mark - Delegates 63 | #pragma mark UITableView 64 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 65 | RBLogInfo* logInfo = _messagesArray[indexPath.row]; 66 | [_alertController setTitle:logInfo.title]; 67 | [_alertController setMessage:logInfo.message]; 68 | [self presentViewController:_alertController 69 | animated:YES 70 | completion:^{ 71 | [tableView deselectRowAtIndexPath:indexPath 72 | animated:YES]; 73 | }]; 74 | } 75 | 76 | #pragma mark - Data Source 77 | #pragma mark UITableView 78 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 79 | return UITableViewAutomaticDimension; 80 | } 81 | 82 | - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 83 | return 44.0f; 84 | } 85 | 86 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 87 | return 0.01f; 88 | } 89 | 90 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 91 | return _messagesArray.count; 92 | } 93 | 94 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 95 | RBLogInfoTableViewCell* cell = (RBLogInfoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:[RBLogInfoTableViewCell cellIdentifier]]; 96 | 97 | RBLogInfo* logInfo = _messagesArray[indexPath.row]; 98 | 99 | [cell updateWithObject:logInfo]; 100 | 101 | return cell; 102 | } 103 | 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFilePickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBImagePickerController.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @class RBFilePickerViewController; 9 | 10 | @protocol RBFilePickerDelegate 11 | 12 | @optional 13 | - (void)filePicker:(RBFilePickerViewController*)picker didSelectFileNamed:(NSString*)fileName withData:(NSData*)data; 14 | 15 | @end 16 | 17 | 18 | @interface RBFilePickerViewController : UIViewController 19 | 20 | @property (weak) id delegate; 21 | 22 | @property (nonatomic, strong) NSString* storageDirectoryPathString; 23 | @property (nonatomic, strong, readonly) NSString* fullStoragePathString; 24 | 25 | - (void)loadFilesInStoragePath; 26 | 27 | - (BOOL)saveData:(NSData*)data withFileName:(NSString*)fileName; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFilePickerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBImagePickerController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBFilePickerViewController.h" 7 | 8 | #import "NSFileWrapper+Extensions.h" 9 | 10 | @interface RBFilePickerViewController () 11 | 12 | @property (nonatomic, weak) IBOutlet UITableView* tableView; 13 | @property (nonatomic, strong) NSMutableArray* localFiles; 14 | 15 | @end 16 | 17 | @implementation RBFilePickerViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | [self loadFilesInStoragePath]; 23 | } 24 | 25 | #pragma mark - Public 26 | - (void)loadFilesInStoragePath { 27 | _localFiles = [NSMutableArray array]; 28 | 29 | if (!self.fullStoragePathString) { 30 | NSString *documentsPathString = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 31 | if (self.storageDirectoryPathString) { 32 | if ([self.storageDirectoryPathString characterAtIndex:0] != '/') { 33 | _storageDirectoryPathString = [NSString stringWithFormat:@"/%@", self.storageDirectoryPathString]; 34 | } 35 | documentsPathString = [documentsPathString stringByAppendingString:self.storageDirectoryPathString]; 36 | } 37 | 38 | if (![[NSFileManager defaultManager] fileExistsAtPath:documentsPathString]) { 39 | NSError* error = nil; 40 | [[NSFileManager defaultManager] createDirectoryAtPath:documentsPathString 41 | withIntermediateDirectories:NO 42 | attributes:nil 43 | error:&error]; 44 | if (error) { 45 | NSLog(@"Error creating directory: %@", error); 46 | } 47 | } 48 | 49 | _fullStoragePathString = documentsPathString; 50 | } 51 | 52 | NSURL* documentsPathURL = [NSURL URLWithString:self.fullStoragePathString]; 53 | 54 | NSArray* fileProperties = @[ 55 | NSURLLocalizedNameKey, 56 | NSURLIsDirectoryKey, 57 | NSURLTotalFileSizeKey 58 | ]; 59 | 60 | NSEnumerator* filesEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:documentsPathURL 61 | includingPropertiesForKeys:fileProperties 62 | options:NSDirectoryEnumerationSkipsHiddenFiles 63 | errorHandler:nil]; 64 | 65 | for (NSURL* fileURL in filesEnumerator) { 66 | NSFileWrapper* fileWrapper = [[NSFileWrapper alloc] initWithURL:fileURL 67 | options:NSFileWrapperReadingImmediate 68 | error:nil]; 69 | if (!fileWrapper.isDirectory) { 70 | [_localFiles addObject:fileWrapper]; 71 | } 72 | } 73 | } 74 | 75 | - (BOOL)saveData:(NSData *)data withFileName:(NSString *)fileName { 76 | NSString* fullFilePath = [self.fullStoragePathString stringByAppendingPathComponent:fileName]; 77 | BOOL successful = NO; 78 | if (![[NSFileManager defaultManager] fileExistsAtPath:fullFilePath]) { 79 | successful = [data writeToFile:fullFilePath 80 | atomically:NO]; 81 | [self loadFilesInStoragePath]; 82 | } else { 83 | NSLog(@"File exists at %@", fileName); 84 | } 85 | return successful; 86 | } 87 | 88 | #pragma mark - Setters 89 | - (void)setStorageDirectoryPathString:(NSString *)storageDirectoryPathString { 90 | _storageDirectoryPathString = storageDirectoryPathString; 91 | [self loadFilesInStoragePath]; 92 | } 93 | 94 | #pragma mark - Actions 95 | - (IBAction)cancelAction:(id)sender { 96 | [self dismissViewControllerAnimated:YES 97 | completion:nil]; 98 | } 99 | 100 | #pragma mark - Delegates 101 | #pragma mark UITableView 102 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 103 | if ([_delegate respondsToSelector:@selector(filePicker:didSelectFileNamed:withData:)]) { 104 | NSFileWrapper* fileWrapper = _localFiles[indexPath.row]; 105 | [_delegate filePicker:self didSelectFileNamed:fileWrapper.preferredFilename withData:fileWrapper.regularFileContents]; 106 | } else { 107 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 108 | } 109 | } 110 | 111 | #pragma mark - Data Source 112 | #pragma mark UITableView 113 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 114 | return _localFiles.count; 115 | } 116 | 117 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 118 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"RBFileTableViewCell"]; 119 | 120 | NSFileWrapper* fileWrapper = _localFiles[indexPath.row]; 121 | 122 | cell.textLabel.text = fileWrapper.preferredFilename; 123 | cell.detailTextLabel.text = fileWrapper.fileSizeString; 124 | 125 | return cell; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFunctionViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RPCViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseViewController.h" 7 | 8 | @class RBFunction; 9 | 10 | @interface RBFunctionViewController : RBBaseViewController 11 | 12 | @property (nonatomic, strong) RBFunction* function; 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFunctionViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RPCViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBFunctionViewController.h" 7 | #import "RBFunction.h" 8 | 9 | #import "RBFilePickerViewController.h" 10 | #import "RBFileView.h" 11 | 12 | @implementation RBFunctionViewController 13 | 14 | - (void)viewWillAppear:(BOOL)animated { 15 | [super viewWillAppear:animated]; 16 | if (!self.navigationItem.rightBarButtonItem) { 17 | UIBarButtonItem* sendBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Send" 18 | style:UIBarButtonItemStyleDone 19 | target:self 20 | action:@selector(sendAction:)]; 21 | self.navigationItem.rightBarButtonItem = sendBarButtonItem; 22 | } 23 | } 24 | 25 | #pragma mark - Overrides 26 | - (void)updateView { 27 | self.title = _function.name; 28 | 29 | self.requestDictionary[RBNameKey] = _function.name; 30 | 31 | [self loadParameters:_function.parameters]; 32 | 33 | [self sdl_loadOptionalFunctionViews:_function]; 34 | } 35 | 36 | #pragma mark - Actions 37 | - (void)sendAction:(id)selector { 38 | [self updateRequestsDictionaryFromSubviews]; 39 | 40 | [self.sdlManager sendRequestDictionary:self.requestDictionary 41 | bulkData:self.bulkData]; 42 | 43 | if (self.navigationController.viewControllers.firstObject != self) { 44 | [self.navigationController popToRootViewControllerAnimated:YES]; 45 | } 46 | } 47 | 48 | #pragma mark - Private 49 | - (void)sdl_loadOptionalFunctionViews:(RBFunction *)function { 50 | if (function.requiresBulkData) { 51 | UIView* lastView = self.scrollView.subviews.lastObject; 52 | 53 | RBFileView* fileView = [[RBFileView alloc] initWithTitle:@"bulkData" 54 | delegate:self]; 55 | 56 | CGRect newFrame = fileView.frame; 57 | newFrame.origin.y = kParamViewSpacing + CGRectGetMaxY(lastView.frame); 58 | fileView.frame = newFrame; 59 | 60 | [self.scrollView addSubview:fileView]; 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFunctionsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBFunctionsViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | #import "RBFunctionViewController.h" 9 | 10 | #import "RBFunction.h" 11 | 12 | @interface RBFunctionsViewController : UITableViewController 13 | 14 | + (RBFunctionViewController*)viewControllerForFunction:(RBFunction*)function; 15 | 16 | @end 17 | 18 | 19 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBFunctionsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBFunctionsViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBFunctionsViewController.h" 7 | 8 | #import "UIAlertController+Minimal.h" 9 | 10 | #import "RBSDLManager.h" 11 | 12 | @interface RBFunctionsViewController () 13 | 14 | @property (strong) NSArray* RPCs; 15 | 16 | @end 17 | 18 | @implementation RBFunctionsViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | [self.tableView registerClass:[UITableViewCell class] 24 | forCellReuseIdentifier:@"RequestTableViewCell"]; 25 | 26 | [[NSNotificationCenter defaultCenter] addObserver:self 27 | selector:@selector(settingsManagerRPCsAvailable:) 28 | name:RBSettingsManagerRPCsAvailableNotification 29 | object:nil]; 30 | } 31 | 32 | - (IBAction)presentSettingsAction:(id)sender { 33 | UIAlertController* alertController = [UIAlertController actionSheetWithTitle:nil 34 | message:nil]; 35 | 36 | [alertController addDestructiveActionWithTitle:@"Stop Proxy" handler:^(UIAlertAction *action) { 37 | [[RBSDLManager sharedManager] disconnect]; 38 | }]; 39 | 40 | [alertController addCancelAction]; 41 | 42 | [self presentViewController:alertController 43 | animated:YES 44 | completion:nil]; 45 | } 46 | 47 | #pragma mark - Notifications 48 | #pragma mark RBSettingsManager 49 | - (void)settingsManagerRPCsAvailable:(NSNotification*)notification { 50 | self.RPCs = [[RBSettingsManager sharedManager] availableRPCs]; 51 | [self.tableView reloadData]; 52 | } 53 | 54 | #pragma mark UITableViewDataSource 55 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 56 | return self.RPCs.count; 57 | } 58 | 59 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 60 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"RequestTableViewCell"]; 61 | RBFunction* function = self.RPCs[indexPath.row]; 62 | cell.textLabel.text = function.name; 63 | cell.imageView.image = function.image; 64 | cell.accessoryType = function.objectDescription ? UITableViewCellAccessoryDetailButton : UITableViewCellAccessoryNone; 65 | return cell; 66 | } 67 | 68 | - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { 69 | RBFunction* function = self.RPCs[indexPath.row]; 70 | UIAlertController* alertController = [UIAlertController alertControllerWithTitle:function.name 71 | message:function.objectDescription 72 | preferredStyle:UIAlertControllerStyleAlert]; 73 | [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" 74 | style:UIAlertActionStyleDefault 75 | handler:nil]]; 76 | [self presentViewController:alertController 77 | animated:YES 78 | completion:nil]; 79 | } 80 | 81 | #pragma mark UITableViewDelegate 82 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 83 | RBFunction* function = self.RPCs[indexPath.row]; 84 | 85 | [self.navigationController pushViewController:[self.class viewControllerForFunction:function] 86 | animated:YES]; 87 | } 88 | 89 | 90 | #pragma mark - Private 91 | #pragma mark Getters 92 | + (NSMutableDictionary*)functionStore { 93 | static NSMutableDictionary* functionStore = nil; 94 | static dispatch_once_t onceToken; 95 | dispatch_once(&onceToken, ^{ 96 | functionStore = [NSMutableDictionary dictionary]; 97 | }); 98 | return functionStore; 99 | } 100 | 101 | #pragma mark Functions 102 | + (RBFunctionViewController*)viewControllerForFunction:(RBFunction*)function { 103 | RBFunctionViewController* viewController = self.functionStore[function.name]; 104 | if (!viewController) { 105 | viewController = [[RBFunctionViewController alloc] initWithNibName:@"RBBaseViewController" 106 | bundle:nil]; 107 | viewController.function = function; 108 | self.functionStore[function.name] = viewController; 109 | } 110 | return viewController; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBModulesTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBModulesTableViewController.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RBModulesTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBModulesTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBModulesTableViewController.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBModulesTableViewController.h" 10 | #import "RBModuleViewController.h" 11 | #import "RBModuleTableViewCell.h" 12 | #import "UIAlertController+Minimal.h" 13 | 14 | #import "RBSDLManager.h" 15 | 16 | @interface RBModulesTableViewController () 17 | 18 | @property (nonatomic, strong) NSArray* modules; 19 | 20 | @end 21 | 22 | @implementation RBModulesTableViewController 23 | 24 | - (void)viewDidLoad { 25 | self.modules = [RBModuleViewController moduleClassNames]; 26 | 27 | [self.tableView registerClass:[RBModuleTableViewCell class] 28 | forCellReuseIdentifier:[RBModuleTableViewCell cellIdentifier]]; 29 | } 30 | 31 | #pragma mark - Data Sources 32 | #pragma mark UITableView 33 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 34 | return self.modules.count; 35 | } 36 | 37 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 38 | RBModuleTableViewCell* cell = (RBModuleTableViewCell*)[tableView dequeueReusableCellWithIdentifier:[RBModuleTableViewCell cellIdentifier]]; 39 | 40 | [cell updateWithObject:self.modules[indexPath.row]]; 41 | 42 | return cell; 43 | } 44 | 45 | #pragma mark - Delegates 46 | #pragma mark UITableView 47 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 48 | NSString* classString = self.modules[indexPath.row]; 49 | Class moduleClass = NSClassFromString(classString); 50 | 51 | if ([moduleClass isSubclassOfClass:[RBModuleViewController class]]) { 52 | RBModuleViewController* viewController = [moduleClass viewController]; 53 | [self.navigationController pushViewController:viewController 54 | animated:YES]; 55 | } 56 | } 57 | 58 | - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { 59 | NSString* classString = self.modules[indexPath.row]; 60 | Class moduleClass = NSClassFromString(classString); 61 | 62 | if ([moduleClass isSubclassOfClass:[RBModuleViewController class]]) { 63 | NSString* moduleDescription = [moduleClass description]; 64 | if (moduleDescription) { 65 | UIAlertController* alertController = [UIAlertController simpleAlertWithTitle:@"Module Description" 66 | message:[moduleClass moduleDescription]]; 67 | [self presentViewController:alertController 68 | animated:YES 69 | completion:nil]; 70 | } 71 | } 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBScrollViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBScrollViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface RBScrollViewController : UIViewController 9 | 10 | @property (nonatomic, readonly) NSNotificationCenter* notificationCenter; 11 | 12 | @property (nonatomic, weak) IBOutlet UIScrollView* scrollView; 13 | @property (nonatomic, weak) IBOutlet NSLayoutConstraint* scrollViewBottomConstraint; 14 | 15 | /* 16 | * 17 | * Override when scrollView is not anchored to bottom of parent view. 18 | * 19 | */ 20 | @property (nonatomic, readonly) CGFloat scrollViewBottomOffset; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBScrollViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBScrollViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBScrollViewController.h" 7 | 8 | @interface RBScrollViewController () 9 | 10 | @property (nonatomic, strong) NSLayoutConstraint* originalBottomConstraint; 11 | 12 | @end 13 | 14 | @implementation RBScrollViewController 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | 19 | [self.notificationCenter addObserver:self 20 | selector:@selector(keyboardWillHideAction:) 21 | name:UIKeyboardWillHideNotification 22 | object:nil]; 23 | [self.notificationCenter addObserver:self 24 | selector:@selector(keyboardWillShowAction:) 25 | name:UIKeyboardWillChangeFrameNotification 26 | object:nil]; 27 | } 28 | 29 | - (void)dealloc { 30 | [self.notificationCenter removeObserver:self]; 31 | } 32 | 33 | #pragma mark - Actions 34 | - (void)keyboardWillHideAction:(NSNotification*)notification { 35 | NSDictionary* info = [notification userInfo]; 36 | NSTimeInterval animationDuration = [info[UIKeyboardAnimationDurationUserInfoKey] floatValue]; 37 | UIViewAnimationOptions animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 38 | 39 | [UIView animateWithDuration:animationDuration 40 | delay:0.0f 41 | options:animationCurve 42 | animations:^{ 43 | _scrollViewBottomConstraint.constant = _originalBottomConstraint.constant; 44 | } completion:nil]; 45 | } 46 | 47 | - (void)keyboardWillShowAction:(NSNotification*)notification { 48 | if (!_originalBottomConstraint) { 49 | _originalBottomConstraint = [_scrollViewBottomConstraint copy]; 50 | } 51 | NSDictionary* info = [notification userInfo]; 52 | CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 53 | CGFloat keyboardHeight = CGRectGetHeight(keyboardFrame); 54 | 55 | NSTimeInterval animationDuration = [info[UIKeyboardAnimationDurationUserInfoKey] floatValue]; 56 | UIViewAnimationOptions animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 57 | 58 | [UIView animateWithDuration:animationDuration 59 | delay:0.0f 60 | options:animationCurve 61 | animations:^{ 62 | _scrollViewBottomConstraint.constant = _originalBottomConstraint.constant + keyboardHeight - self.scrollViewBottomOffset; 63 | } completion:nil]; 64 | } 65 | 66 | #pragma mark - Getters 67 | - (NSNotificationCenter*)notificationCenter { 68 | return [NSNotificationCenter defaultCenter]; 69 | } 70 | 71 | - (CGFloat)scrollViewBottomOffset { 72 | return 0.0f; 73 | } 74 | 75 | #pragma mark - Delegates 76 | #pragma mark UITextField 77 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 78 | [textField resignFirstResponder]; 79 | return YES; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBSettingsViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseViewController.h" 7 | 8 | @interface RBSettingsViewController : RBBaseViewController 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBSettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBSettingsViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSettingsViewController.h" 7 | #import "RBAppRegistrationViewController.h" 8 | #import "RBSpecFilesViewController.h" 9 | 10 | #import "RBParser.h" 11 | 12 | #import "RBElementTextField.h" 13 | #import "UIView+Util.h" 14 | 15 | #import "RBSpecFile.h" 16 | 17 | typedef NS_ENUM(NSUInteger, RBURLStatus) { 18 | RBURLStatusLoading, 19 | RBURLStatusError, 20 | RBURLStatusSuccess 21 | }; 22 | 23 | @interface RBSettingsViewController () 24 | 25 | @property (nonatomic, readonly) UIBarButtonItem* cancelBarButton; 26 | @property (nonatomic, readonly) UIBarButtonItem* nextBarButton; 27 | 28 | @property (nonatomic, weak) IBOutlet UILabel* specFileLabel; 29 | @property (nonatomic, weak) IBOutlet RBElementTextField* connectionTypeTextField; 30 | 31 | @property (nonatomic, weak) IBOutlet UIView* tcpContainerView; 32 | @property (nonatomic, strong) IBOutlet NSLayoutConstraint* tcpContainerHeight; 33 | @property (nonatomic, strong) NSLayoutConstraint* originalTCPContainerHeight; 34 | @property (nonatomic, weak) IBOutlet UITextField* ipAddressTextField; 35 | @property (nonatomic, weak) IBOutlet UITextField* portTextField; 36 | 37 | @end 38 | 39 | @implementation RBSettingsViewController 40 | 41 | @synthesize cancelBarButton = _cancelBarButton; 42 | @synthesize nextBarButton = _nextBarButton; 43 | 44 | - (void)viewDidLoad { 45 | [super viewDidLoad]; 46 | 47 | [self.notificationCenter addObserver:self 48 | selector:@selector(settingsManagerSpecFileStatusDidChange:) 49 | name:RBSettingsManagerSpecFileStatusDidChangeNotification 50 | object:nil]; 51 | 52 | self.navigationItem.rightBarButtonItem = self.nextBarButton; 53 | 54 | self.navigationItem.rightBarButtonItem.enabled = NO; 55 | 56 | if (self.settingsManager.specFile) { 57 | _specFileLabel.text = self.settingsManager.specFile.fileName; 58 | self.navigationItem.rightBarButtonItem.enabled = YES; 59 | } 60 | 61 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 62 | CGRectGetMaxY(_tcpContainerView.frame)); 63 | 64 | _connectionTypeTextField.elements = self.settingsManager.connectionTypes; 65 | _connectionTypeTextField.currentElement = self.settingsManager.connectionTypeString; 66 | _connectionTypeTextField.inputView = self.pickerView; 67 | _connectionTypeTextField.inputAccessoryView = self.doneToolbar; 68 | _connectionTypeTextField.text = self.settingsManager.connectionTypeString; 69 | 70 | [self sdl_updateTCPConnectionView]; 71 | 72 | _ipAddressTextField.text = self.settingsManager.ipAddress; 73 | _portTextField.text = self.settingsManager.port; 74 | } 75 | 76 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 77 | if ([segue.identifier isEqualToString:NSStringFromClass([RBSpecFilesViewController class])]) { 78 | RBSpecFilesViewController* viewController = (RBSpecFilesViewController*)segue.destinationViewController; 79 | viewController.delegate = self; 80 | } 81 | } 82 | 83 | #pragma mark - Actions 84 | - (void)startAction:(id)sender { 85 | RBSDLConfiguration* configuration = nil; 86 | if ([_connectionTypeTextField.text isEqualToString:SDLConnectionTypeStringiAP]) { 87 | configuration = [RBSDLConfiguration defaultConfiguration]; 88 | } else if ([_connectionTypeTextField.text isEqualToString:SDLConnectionTypeStringTCP]) { 89 | configuration = [RBSDLConfiguration tcpConfiguration:_ipAddressTextField.text 90 | port:_portTextField.text]; 91 | } 92 | 93 | [self sdl_saveSettings]; 94 | 95 | RBAppRegistrationViewController* viewController = [[RBAppRegistrationViewController alloc] initWithNibName:@"RBBaseViewController" bundle:nil]; 96 | viewController.sdlConfiguration = configuration; 97 | viewController.function = [[RBParser sharedParser] functionOfType:@"RegisterAppInterface"]; 98 | [self.navigationController pushViewController:viewController animated:YES]; 99 | } 100 | 101 | #pragma mark - Delegates 102 | #pragma mark UITextField 103 | - (void)textFieldDidEndEditing:(UITextField *)textField { 104 | if (textField == _connectionTypeTextField) { 105 | [self sdl_updateTCPConnectionView]; 106 | } 107 | } 108 | 109 | #pragma mark - RBSpecFilesViewControllerDelegate 110 | - (void)specFilesViewController:(RBSpecFilesViewController *)viewController didSelectSpecFile:(RBSpecFile *)specFile { 111 | [viewController.navigationController popViewControllerAnimated:YES]; 112 | self.settingsManager.specFile = specFile; 113 | self.navigationItem.rightBarButtonItem.enabled = YES; 114 | _specFileLabel.text = [[[RBSettingsManager sharedManager] specFile] fileName]; 115 | 116 | } 117 | 118 | #pragma mark - Getters 119 | - (UIBarButtonItem*)nextBarButton { 120 | if (!_nextBarButton) { 121 | _nextBarButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" 122 | style:UIBarButtonItemStyleDone 123 | target:self 124 | action:@selector(startAction:)]; 125 | } 126 | return _nextBarButton; 127 | } 128 | 129 | #pragma mark - Notifications 130 | #pragma mark RBSettingsManager 131 | - (void)settingsManagerSpecFileStatusDidChange:(NSNotification*)notification { 132 | NSError* error = notification.userInfo[RBSettingsManagerNotificationErrorKey]; 133 | NSString* newErrorLabel = nil; 134 | BOOL connectButtonEnabled = YES; 135 | if (error) { 136 | connectButtonEnabled = NO; 137 | newErrorLabel = error.localizedDescription; 138 | } else { 139 | dispatch_async(dispatch_get_main_queue(), ^{ 140 | if ([[RBSettingsManager sharedManager] specFile]) { 141 | self.navigationItem.rightBarButtonItem.enabled = YES; 142 | _specFileLabel.text = [[[RBSettingsManager sharedManager] specFile] fileName]; 143 | } 144 | }); 145 | } 146 | } 147 | 148 | #pragma mark - Private Helpers 149 | - (void)sdl_saveSettings { 150 | self.settingsManager.connectionTypeString = _connectionTypeTextField.text; 151 | self.settingsManager.ipAddress = _ipAddressTextField.text; 152 | self.settingsManager.port = _portTextField.text; 153 | } 154 | 155 | - (void)sdl_updateTCPConnectionView { 156 | if (!_originalTCPContainerHeight) { 157 | _originalTCPContainerHeight = [_tcpContainerHeight copy]; 158 | } 159 | if ([_connectionTypeTextField.text isEqualToString:SDLConnectionTypeStringiAP]) { 160 | _tcpContainerHeight.constant = 0; 161 | } else { 162 | _tcpContainerHeight.constant = _originalTCPContainerHeight.constant; 163 | } 164 | } 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBSpecFilesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBSpecFilesViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import "RBSpecFile.h" 8 | 9 | @class RBSpecFilesViewController; 10 | 11 | @protocol RBSpecFilesViewControllerDelegate 12 | 13 | - (void)specFilesViewController:(RBSpecFilesViewController*)viewController didSelectSpecFile:(RBSpecFile*)specFile; 14 | 15 | @end 16 | 17 | @interface RBSpecFilesViewController : UIViewController 18 | 19 | @property (weak) id delegate; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBSpecFilesViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBSpecFilesViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSpecFilesViewController.h" 7 | 8 | #import "UIAlertController+Minimal.h" 9 | 10 | #import "RBSettingsManager.h" 11 | 12 | @interface RBSpecFilesViewController () 13 | 14 | @property (nonatomic, weak) NSIndexPath* selectedIndex; 15 | 16 | @property (nonatomic, weak) IBOutlet UITableView* tableView; 17 | @property (nonatomic, weak) IBOutlet UITextField* specURLTextField; 18 | @property (nonatomic, strong, readonly) UIBarButtonItem* addBarButton; 19 | 20 | @property (nonatomic, strong) NSArray* specXMLs; 21 | 22 | @property (nonatomic, readonly) RBSpecFile* currentSpecFile; 23 | 24 | @property (nonatomic, getter=isCreatingNewSpec) BOOL creatingNewSpec; 25 | 26 | @end 27 | 28 | @implementation RBSpecFilesViewController 29 | 30 | @synthesize addBarButton = _addBarButton; 31 | @synthesize creatingNewSpec = _creatingNewSpec; 32 | 33 | - (void)viewDidLoad { 34 | [super viewDidLoad]; 35 | 36 | _specURLTextField.text = @"https://raw.githubusercontent.com/smartdevicelink/rpc_spec/master/spec.xml"; 37 | 38 | _specXMLs = [[RBSettingsManager sharedManager] specXMLs]; 39 | } 40 | 41 | #pragma mark - Actions 42 | - (IBAction)addAction:(id)selector { 43 | UIBarButtonItem* cancelBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 44 | target:self 45 | action:@selector(cancelAction:)]; 46 | UIBarButtonItem* saveBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave 47 | target:self 48 | action:@selector(saveAction:)]; 49 | self.navigationItem.leftBarButtonItem = cancelBarButton; 50 | self.navigationItem.rightBarButtonItem = saveBarButtonItem; 51 | [UIView animateWithDuration:0.3 animations:^{ 52 | _tableView.alpha = 0.0f; 53 | } completion:^(BOOL finished) { 54 | [_specURLTextField becomeFirstResponder]; 55 | }]; 56 | } 57 | 58 | - (void)cancelAction:(id)selector { 59 | [_specURLTextField resignFirstResponder]; 60 | self.navigationItem.leftBarButtonItem = nil; 61 | self.navigationItem.rightBarButtonItem = self.addBarButton; 62 | 63 | _creatingNewSpec = NO; 64 | 65 | [UIView animateWithDuration:0.3 animations:^{ 66 | _tableView.alpha = 1.0f; 67 | } completion:^(BOOL finished) { 68 | }]; 69 | } 70 | 71 | - (void)saveAction:(id)selector { 72 | [_specURLTextField resignFirstResponder]; 73 | 74 | self.navigationItem.leftBarButtonItem.enabled = NO; 75 | self.navigationItem.rightBarButtonItem.enabled = NO; 76 | 77 | _creatingNewSpec = YES; 78 | 79 | RBSpecFile* specFile = [[RBSpecFile alloc] initWithURL:[NSURL URLWithString:_specURLTextField.text]]; 80 | specFile.delegate = self; 81 | [specFile fetchUrl]; 82 | } 83 | 84 | #pragma mark - Data Source 85 | #pragma mark UITableView 86 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 87 | return _specXMLs.count; 88 | } 89 | 90 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 91 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"RBSpecFileTableViewCell"]; 92 | 93 | RBSpecFile* file = _specXMLs[indexPath.row]; 94 | 95 | cell.textLabel.text = file.fileName; 96 | 97 | cell.accessoryType = [file isEqual:self.currentSpecFile] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 98 | 99 | return cell; 100 | } 101 | 102 | #pragma mark - Delegates 103 | #pragma mark UITableView 104 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 105 | RBSpecFile* file = _specXMLs[indexPath.row]; 106 | 107 | if (!file.data) { 108 | file.delegate = self; 109 | [file fetchUrl]; 110 | } else { 111 | if ([self.delegate respondsToSelector:@selector(specFilesViewController:didSelectSpecFile:)]) { 112 | [self.delegate specFilesViewController:self 113 | didSelectSpecFile:_specXMLs[indexPath.row]]; 114 | } 115 | } 116 | } 117 | 118 | #pragma mark RBSpecFile 119 | - (void)specFile:(RBSpecFile *)file fetchUrlDidFinishWithError:(NSError *)error { 120 | UIAlertController* alertController = [UIAlertController simpleErrorAlertWithMessage:error.localizedDescription]; 121 | dispatch_async(dispatch_get_main_queue(), ^{ 122 | self.navigationItem.leftBarButtonItem.enabled = YES; 123 | self.navigationItem.rightBarButtonItem.enabled = YES; 124 | [self presentViewController:alertController 125 | animated:YES 126 | completion:nil]; 127 | }); 128 | } 129 | 130 | - (void)specFileFetchUrlDidFinish:(RBSpecFile *)file { 131 | if (self.isCreatingNewSpec) { 132 | _creatingNewSpec = NO; 133 | _specXMLs = [[RBSettingsManager sharedManager] specXMLs]; 134 | 135 | dispatch_async(dispatch_get_main_queue(), ^{ 136 | self.navigationItem.leftBarButtonItem.enabled = YES; 137 | self.navigationItem.rightBarButtonItem.enabled = YES; 138 | 139 | [_tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:_specXMLs.count - 1 inSection:0]] 140 | withRowAnimation:UITableViewRowAnimationAutomatic]; 141 | 142 | self.navigationItem.leftBarButtonItem = nil; 143 | self.navigationItem.rightBarButtonItem = self.addBarButton; 144 | 145 | [UIView animateWithDuration:0.3 animations:^{ 146 | _tableView.alpha = 1.0f; 147 | } completion:^(BOOL finished) { 148 | _specURLTextField.text = nil; 149 | }]; 150 | }); 151 | } else { 152 | if ([self.delegate respondsToSelector:@selector(specFilesViewController:didSelectSpecFile:)]) { 153 | [self.delegate specFilesViewController:self 154 | didSelectSpecFile:file]; 155 | } 156 | } 157 | } 158 | 159 | #pragma mark - Private 160 | #pragma mark Getters 161 | - (UIBarButtonItem*)addBarButton { 162 | if (!_addBarButton) { 163 | _addBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 164 | target:self 165 | action:@selector(addAction:)]; 166 | } 167 | return _addBarButton; 168 | } 169 | 170 | - (RBSpecFile*)currentSpecFile { 171 | return [[RBSettingsManager sharedManager] specFile]; 172 | } 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBStructViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBStructViewController.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseViewController.h" 7 | 8 | @class RBStructViewController; 9 | 10 | @protocol RBStructDelegate 11 | 12 | - (void)structViewController:(RBStructViewController*)viewController didCreateStruct:(NSDictionary*)structDictionary; 13 | 14 | @end 15 | 16 | @class RBStruct; 17 | 18 | @interface RBStructViewController : RBBaseViewController 19 | 20 | @property (strong) NSMutableDictionary* structDictionary; 21 | @property (weak) id delegate; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RPC Builder/View Controllers/RBStructViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBStructViewController.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBStructViewController.h" 7 | #import "RBArrayViewController.h" 8 | 9 | #import "RBStruct.h" 10 | 11 | @implementation RBStructViewController 12 | 13 | - (void)updateView { 14 | self.title = self.structObj.name; 15 | 16 | UIBarButtonItem* saveBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave 17 | target:self 18 | action:@selector(saveAction:)]; 19 | self.navigationItem.rightBarButtonItem = saveBarButton; 20 | 21 | self.parametersDictionary = [NSMutableDictionary dictionary]; 22 | 23 | [self loadParameters:self.structObj.parameters]; 24 | } 25 | 26 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 27 | if ([segue.destinationViewController isKindOfClass:[RBArrayViewController class]]) { 28 | RBArrayViewController* viewController = segue.destinationViewController; 29 | viewController.parametersDictionary = self.parametersDictionary; 30 | } 31 | } 32 | 33 | #pragma mark - Actions 34 | - (void)saveAction:(id)selector { 35 | if ([_delegate respondsToSelector:@selector(structViewController:didCreateStruct:)]) { 36 | [_delegate structViewController:self 37 | didCreateStruct:[self sdl_parametersDictionaryFromSubviews]]; 38 | } else { 39 | self.parametersDictionary[self.param.name] = [self sdl_parametersDictionaryFromSubviews]; 40 | [self.navigationController popViewControllerAnimated:YES]; 41 | } 42 | } 43 | 44 | #pragma mark - Private 45 | - (NSDictionary*)sdl_parametersDictionaryFromSubviews { 46 | NSMutableDictionary* parameters = [NSMutableDictionary dictionaryWithDictionary:self.parametersDictionary]; 47 | for (UIView* view in self.scrollView.subviews) { 48 | if ([view isKindOfClass:[RBParamView class]]) { 49 | RBParamView* paramView = (RBParamView*)view; 50 | [paramView addToDictionary:parameters]; 51 | } 52 | } 53 | return [parameters copy]; 54 | } 55 | 56 | #pragma mark - Overrides 57 | // We are placing this here because we actually don't want to use RBBaseViewController's implementation. 58 | - (void)textFieldDidEndEditing:(UITextField *)textField { } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /RPC Builder/Views/UILabel/RBNameLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBNameLabel.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @class RBNameLabel; 9 | 10 | @protocol RBNameLabelDelegate 11 | 12 | - (void)nameLabel:(RBNameLabel*)nameLabel shouldPresentViewController:(UIViewController*)viewController; 13 | - (void)nameLabel:(RBNameLabel *)nameLabel enabledStateChanged:(BOOL)enabled; 14 | 15 | @end 16 | 17 | @class RBParam; 18 | 19 | @interface RBNameLabel : UILabel 20 | 21 | - (instancetype)initWithParam:(RBParam*)param; 22 | - (instancetype)initWithText:(NSString*)text isMandatory:(BOOL)isMandatory; 23 | 24 | - (void)setConnectedView:(UIView *)connectedView updateFrame:(BOOL)updateFrame; 25 | 26 | @property (nonatomic, readonly) RBParam* param; 27 | 28 | @property (nonatomic, weak) NSString* customDescription; 29 | 30 | @property (nonatomic, readonly) UIView* connectedView; 31 | 32 | @property (weak) id delegate; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /RPC Builder/Views/UILabel/RBNameLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBNameLabel.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBNameLabel.h" 7 | 8 | #import "RBDeviceInformation.h" 9 | #import "RBParam.h" 10 | 11 | #import "UIView+Util.h" 12 | 13 | #import "UIAlertController+Minimal.h" 14 | 15 | #import "RBParamView.h" 16 | 17 | @implementation RBNameLabel 18 | 19 | - (instancetype)initWithParam:(RBParam *)param { 20 | if (self = [self initWithText:param.name isMandatory:param.isMandatory]) { 21 | _param = param; 22 | } 23 | return self; 24 | } 25 | 26 | - (instancetype)initWithText:(NSString*)text isMandatory:(BOOL)isMandatory { 27 | if (self = [super initWithFrame:CGRectZero]) { 28 | self.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; 29 | NSString* nameString = [text stringByAppendingFormat:@"%@", (isMandatory ? @"*" : @"")]; 30 | nameString = [nameString stringByReplacingOccurrencesOfString:@"(? 7 | 8 | @class RBParam; 9 | 10 | @interface RBSwitch : UISwitch 11 | 12 | - (instancetype)initWithParam:(RBParam*)param referenceFrame:(CGRect)frame; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/Views/UISwitch/RBSwitch.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBSwitch.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBSwitch.h" 7 | 8 | #import "RBParam.h" 9 | 10 | #import "UIView+Util.h" 11 | 12 | @implementation RBSwitch 13 | 14 | - (instancetype)initWithParam:(RBParam*)param referenceFrame:(CGRect)frame { 15 | if (self = [super initWithFrame:CGRectZero]) { 16 | [self rightAlignmentWithReferenceRect:frame]; 17 | if (param.defaultValue) { 18 | if ([param.defaultValue isEqualToString:RBTypeBooleanTrueValue]) { 19 | self.on = YES; 20 | } else if ([param.defaultValue isEqualToString:RBTypeBooleanFalseValue]) { 21 | self.on = NO; 22 | } 23 | } 24 | } 25 | return self; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBBaseTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBBaseTableViewCell.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface RBBaseTableViewCell : UITableViewCell 9 | 10 | - (void)updateWithObject:(id)object; 11 | 12 | + (NSString*)cellIdentifier; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBBaseTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBBaseTableViewCell.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseTableViewCell.h" 7 | 8 | @implementation RBBaseTableViewCell 9 | 10 | - (void)updateWithObject:(id)object { 11 | [self doesNotRecognizeSelector:_cmd]; 12 | } 13 | 14 | + (NSString*)cellIdentifier { 15 | return NSStringFromClass(self.class); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBLogInfoTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBLogInfoTableViewCell.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBBaseTableViewCell.h" 7 | 8 | @interface RBLogInfoTableViewCell : RBBaseTableViewCell 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBLogInfoTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBLogInfoTableViewCell.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBLogInfoTableViewCell.h" 7 | #import "RBLogInfo.h" 8 | 9 | @interface RBLogInfoTableViewCell () 10 | 11 | @property (nonatomic, weak) IBOutlet UILabel* titleLabel; 12 | @property (nonatomic, weak) IBOutlet UILabel* accessoryLabel; 13 | @property (nonatomic, weak) IBOutlet UIView* notificationTypeView; 14 | 15 | @end 16 | 17 | @implementation RBLogInfoTableViewCell 18 | 19 | - (void)updateWithObject:(id)object { 20 | RBLogInfo* logInfo = (RBLogInfo*)object; 21 | self.titleLabel.text = logInfo.title; 22 | self.accessoryLabel.attributedText = [self sdl_attributedStringForDateString:logInfo.dateString 23 | andResultString:logInfo.resultString 24 | withColor:logInfo.resultColor]; 25 | self.notificationTypeView.backgroundColor = logInfo.typeColor; 26 | } 27 | 28 | - (NSAttributedString*)sdl_attributedStringForDateString:(NSString*)dateString andResultString:(NSString*)resultString withColor:(UIColor*)resultColor { 29 | NSMutableAttributedString* attributedString = [[NSMutableAttributedString alloc] initWithString:dateString]; 30 | if (resultString.length) { 31 | NSDictionary* attributes = @{NSForegroundColorAttributeName : resultColor, 32 | NSFontAttributeName : [UIFont boldSystemFontOfSize:self.accessoryLabel.font.pointSize]}; 33 | NSMutableAttributedString* resultAttributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@" - %@", resultString]]; 34 | [resultAttributedString addAttributes:attributes range:NSMakeRange(3, resultString.length)]; 35 | [attributedString appendAttributedString:resultAttributedString]; 36 | } 37 | return attributedString; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBModuleTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBModuleTableViewCell.h 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBBaseTableViewCell.h" 10 | 11 | @interface RBModuleTableViewCell : RBBaseTableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITableViewCell/RBModuleTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBModuleTableViewCell.m 3 | // RPC Builder 4 | // 5 | // Created by Muller, Alexander (A.) on 3/29/16. 6 | // Copyright © 2016 Ford Motor Company. All rights reserved. 7 | // 8 | 9 | #import "RBModuleTableViewCell.h" 10 | #import "RBModuleViewController.h" 11 | 12 | @implementation RBModuleTableViewCell 13 | 14 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 15 | if (self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]) { 16 | 17 | } 18 | return self; 19 | } 20 | 21 | - (void)updateWithObject:(id)object { 22 | if ([object isKindOfClass:[NSString class]]) { 23 | Class moduleClass = NSClassFromString(object); 24 | 25 | if ([moduleClass isSubclassOfClass:[RBModuleViewController class]]) { 26 | self.textLabel.text = [moduleClass moduleTitle]; 27 | if (![[moduleClass minimumSupportedVersion] isEqualToString:[RBModuleViewController minimumSupportedVersion]]) { 28 | self.detailTextLabel.text = [NSString stringWithFormat:@"Requires iOS %@", [moduleClass minimumSupportedVersion]]; 29 | } else { 30 | self.detailTextLabel.text = nil; 31 | } 32 | self.accessoryType = [moduleClass moduleDescription] ? UITableViewCellAccessoryDetailButton : UITableViewCellAccessoryNone; 33 | self.imageView.image = [moduleClass moduleImage]; 34 | } 35 | } else { 36 | NSLog(@"error"); 37 | } 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBElementTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBElementTextField.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBTextField.h" 7 | 8 | @class RBElement; 9 | 10 | @interface RBElementTextField : RBTextField 11 | 12 | - (instancetype)initWithElements:(NSArray*)elements referenceFrame:(CGRect)frame; 13 | 14 | @property (nonatomic, strong) NSArray* elements; 15 | @property (nonatomic, weak) id currentElement; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBElementTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBElementTextField.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBElementTextField.h" 7 | #import "RBElement.h" 8 | 9 | @implementation RBElementTextField { 10 | NSUInteger _currentElementIndex; 11 | } 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame { 14 | if (self = [super initWithFrame:frame]) { 15 | [self sdl_commonInitializer]; 16 | } 17 | return self; 18 | } 19 | 20 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 21 | if (self = [super initWithCoder:aDecoder]) { 22 | [self sdl_commonInitializer]; 23 | } 24 | return self; 25 | } 26 | 27 | - (instancetype)initWithElements:(NSArray*)elements referenceFrame:(CGRect)frame { 28 | if (self = [super initWithReferenceFrame:frame]) { 29 | self.elements = elements; 30 | self.textAlignment = NSTextAlignmentRight; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)setCurrentElement:(id)currentElement { 36 | _currentElement = currentElement; 37 | _currentElementIndex = [self.elements indexOfObject:currentElement]; 38 | self.text = [self sdl_stringForElement:currentElement]; 39 | } 40 | 41 | - (void)setElements:(NSArray *)elements { 42 | _elements = elements; 43 | _currentElementIndex = 0; 44 | self.currentElement = elements[_currentElementIndex]; 45 | } 46 | 47 | // This override fixes an issue if the user scrolls quickly and quits before UIPickerView's 48 | // pickerView:didSelectRow:inComponent: is called. 49 | - (BOOL)resignFirstResponder { 50 | if ([self.inputView isKindOfClass:[UIPickerView class]]) { 51 | UIPickerView* pickerView = (UIPickerView*)self.inputView; 52 | NSUInteger selectedIndexPath = [pickerView selectedRowInComponent:0]; 53 | self.currentElement = _elements[selectedIndexPath]; 54 | } 55 | return [super resignFirstResponder]; 56 | } 57 | 58 | #pragma mark - Delegates 59 | #pragma mark UIPickerView 60 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 61 | self.currentElement = self.elements[row]; 62 | } 63 | 64 | #pragma mark - Data Source 65 | #pragma mark UIPickerView 66 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 67 | return 1; 68 | } 69 | 70 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 71 | return self.elements.count; 72 | } 73 | 74 | - (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 75 | id element = self.elements[row]; 76 | return [self sdl_stringForElement:element]; 77 | } 78 | 79 | #pragma mark - Notifications 80 | #pragma mark UITextField 81 | - (void)textFieldDidBeginEditing:(NSNotification*)notification { 82 | if (notification.object == self) { 83 | if ([self.inputView isKindOfClass:[UIPickerView class]]) { 84 | UIPickerView* pickerView = (UIPickerView*)self.inputView; 85 | pickerView.delegate = self; 86 | pickerView.dataSource = self; 87 | [pickerView selectRow:_currentElementIndex 88 | inComponent:0 89 | animated:YES]; 90 | } 91 | } 92 | } 93 | 94 | #pragma mark - Private Helpers 95 | - (void)sdl_commonInitializer { 96 | [[NSNotificationCenter defaultCenter] addObserver:self 97 | selector:@selector(textFieldDidBeginEditing:) 98 | name:UITextFieldTextDidBeginEditingNotification 99 | object:nil]; 100 | } 101 | 102 | - (NSString*)sdl_stringForElement:(id)element { 103 | if ([element isKindOfClass:[RBElement class]]) { 104 | return [(RBElement*)element name]; 105 | } else if ([element isKindOfClass:[NSString class]]) { 106 | return element; 107 | } 108 | 109 | NSAssert(NO, @"Unknown type of element"); 110 | return nil; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBParamTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBParamTextField.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBTextField.h" 7 | 8 | @class RBParam; 9 | 10 | @interface RBParamTextField : RBTextField 11 | 12 | - (instancetype)initWithParam:(RBParam*)param referenceFrame:(CGRect)frame; 13 | 14 | @property (nonatomic, weak) RBParam* parameter; 15 | @property (nonatomic, readonly) NSString* paramType; 16 | @property (nonatomic, readonly) NSString* paramName; 17 | 18 | @property (nonatomic, readonly) id value; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBParamTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBParamTextField.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBParamTextField.h" 7 | #import "RBParam.h" 8 | 9 | @implementation RBParamTextField 10 | 11 | - (instancetype)initWithParam:(RBParam *)param referenceFrame:(CGRect)frame { 12 | if (self = [super initWithReferenceFrame:frame]) { 13 | self.parameter = param; 14 | } 15 | 16 | return self; 17 | } 18 | 19 | #pragma mark - Getters 20 | - (id)value { 21 | if ([self.paramType isEqualToString:RBTypeStringKey]) { 22 | return self.text; 23 | } else if ([self.paramType isEqualToString:RBTypeIntegerKey]) { 24 | return @([self.text integerValue]); 25 | } else if ([self.paramType isEqualToString:RBTypeLongKey]) { 26 | return @([self.text longLongValue]); 27 | } else if ([self.paramType isEqualToString:RBTypeFloatKey]) { 28 | return @([self.text floatValue]); 29 | } else if ([self.paramType isEqualToString:RBTypeDoubleKey]) { 30 | return @([self.text doubleValue]); 31 | } else { 32 | return nil; 33 | } 34 | } 35 | 36 | - (NSString*)paramType { 37 | return self.parameter.type; 38 | } 39 | 40 | - (NSString*)paramName { 41 | return self.parameter.name; 42 | } 43 | 44 | #pragma mark - Setters 45 | - (void)setParameter:(RBParam *)parameter { 46 | _parameter = parameter; 47 | 48 | if ([self.paramType isEqualToString:RBTypeStringKey]) { 49 | self.keyboardType = UIKeyboardTypeAlphabet; 50 | } else if ([self.paramType isEqualToString:RBTypeIntegerKey]) { 51 | self.keyboardType = UIKeyboardTypeNumberPad; 52 | } else if ([self.paramType isEqualToString:RBTypeLongKey] 53 | || [self.paramType isEqualToString:RBTypeFloatKey] 54 | || [self.paramType isEqualToString:RBTypeDoubleKey]) { 55 | self.keyboardType = UIKeyboardTypeNumbersAndPunctuation; 56 | } 57 | 58 | if (parameter.defaultValue) { 59 | self.text = parameter.defaultValue; 60 | } 61 | 62 | if (parameter.minValue 63 | && parameter.maxValue) { 64 | self.placeholder = [NSString stringWithFormat:@"%li - %li", (long)parameter.minValue.integerValue, (long)parameter.maxValue.integerValue]; 65 | } 66 | 67 | if (parameter.maxLength) { 68 | self.placeholder = [NSString stringWithFormat:@"%li characters", (long)parameter.maxLength.integerValue]; 69 | } 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBTextField.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | @interface RBTextField : UITextField 9 | 10 | - (instancetype)initWithReferenceFrame:(CGRect)frame; 11 | 12 | - (id)copyAs:(Class)copyClass; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/Views/UITextField/RBTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBTextField.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBTextField.h" 7 | 8 | #import "UIView+Util.h" 9 | 10 | @implementation RBTextField 11 | 12 | - (instancetype)initWithReferenceFrame:(CGRect)frame { 13 | if (self = [self initWithFrame:CGRectZero]) { 14 | [self bottomAlignmentWithReferenceRect:frame]; 15 | } 16 | 17 | return self; 18 | } 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame { 21 | if (self = [super initWithFrame:frame]) { 22 | self.borderStyle = UITextBorderStyleRoundedRect; 23 | self.returnKeyType = UIReturnKeyDone; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | - (id)copyAs:(Class)copyClass { 30 | if (![copyClass isSubclassOfClass:[self class]]) { 31 | return nil; 32 | } 33 | id newCopy = [[copyClass alloc] initWithFrame:self.frame]; 34 | [newCopy setDelegate:self.delegate]; 35 | 36 | return newCopy; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RPC Builder/Views/UIView/RBFileView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBImageView.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBParamView.h" 7 | 8 | @interface RBFileView : RBParamView 9 | 10 | - (instancetype)initWithTitle:(NSString*)title delegate:(id)delegate; 11 | 12 | @property (nonatomic, strong, readonly) NSData* fileData; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RPC Builder/Views/UIView/RBParamView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBParamView.h 3 | // RPC Builder 4 | // 5 | 6 | #import "RBView.h" 7 | 8 | #import "RBParam.h" 9 | 10 | #import "RBDeviceInformation.h" 11 | #import "RBNameLabel.h" 12 | 13 | @class RBParamView; 14 | 15 | @protocol RBParamViewDelegate 16 | 17 | - (void)paramView:(RBParamView*)view shouldPresentViewController:(UIViewController*)viewController; 18 | - (void)paramViewShouldPresentPickerView:(RBParamView *)view; 19 | 20 | @end 21 | 22 | 23 | 24 | @class RBStruct; 25 | @class RBEnum; 26 | @class RBElement; 27 | 28 | @interface RBParamView : RBView 29 | 30 | - (instancetype)initWithParam:(RBParam*)param delegate:(id)delegate; 31 | 32 | - (void)addTapGestureRecognizerForObject:(id)target action:(SEL)selector; 33 | - (void)addSelfTapGestureRecognizerWithAction:(SEL)selector; 34 | 35 | - (UIImageView*)createChevronImageView; 36 | 37 | - (BOOL)addToDictionary:(NSMutableDictionary*)dictionary; 38 | 39 | @property (nonatomic, readonly) RBParam* param; 40 | @property (nonatomic, readonly) RBStruct* structObj; 41 | @property (nonatomic, readonly) RBEnum* enumObj; 42 | 43 | @property (nonatomic, readonly) UIView* inputView; 44 | 45 | @property (nonatomic, getter=isEnabled) BOOL enabled; 46 | 47 | @property (nonatomic, readonly) id value; 48 | 49 | @property (weak) id delegate; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /RPC Builder/Views/UIView/RBView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RBView.h 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | 8 | extern const CGFloat kViewSpacing; 9 | extern const CGFloat kMinViewHeight; 10 | 11 | @interface RBView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RPC Builder/Views/UIView/RBView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RBView.m 3 | // RPC Builder 4 | // 5 | 6 | #import "RBView.h" 7 | 8 | #import "RBDeviceInformation.h" 9 | 10 | const CGFloat kViewSpacing = 8.0f; 11 | const CGFloat kMinViewHeight = 30.0f; 12 | 13 | @implementation RBView 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RPC Builder/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RPC Builder 4 | // 5 | 6 | #import 7 | #import "AppDelegate.h" 8 | 9 | int main(int argc, char * argv[]) { 10 | @autoreleasepool { 11 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ReadmeFiles/AddCommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/AddCommand.png -------------------------------------------------------------------------------- /ReadmeFiles/Connecting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Connecting.png -------------------------------------------------------------------------------- /ReadmeFiles/Console-RAI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Console-RAI.png -------------------------------------------------------------------------------- /ReadmeFiles/Console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Console.png -------------------------------------------------------------------------------- /ReadmeFiles/EnabledDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/EnabledDisabled.png -------------------------------------------------------------------------------- /ReadmeFiles/MainField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/MainField.png -------------------------------------------------------------------------------- /ReadmeFiles/Modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Modules.png -------------------------------------------------------------------------------- /ReadmeFiles/RPCs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/RPCs.png -------------------------------------------------------------------------------- /ReadmeFiles/RegisterAppInterface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/RegisterAppInterface.png -------------------------------------------------------------------------------- /ReadmeFiles/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Settings.png -------------------------------------------------------------------------------- /ReadmeFiles/Show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartdevicelink/rpc_builder_app_ios/6a2fe816177caa8e08171ec72aece01a03fd6054/ReadmeFiles/Show.png --------------------------------------------------------------------------------