Integrating NSUserDefaults plugin to iOS (#291)

Summary:
I have a few details left, but its almost done. This PR addresses #145

- The NSUserDefaults plugin uses the SharedPreferences Desktop Part since we can reuse all of it.
- The NSUserDefaults plugin uses swizzling in order to be notified of what specific event changed at runtime.
- Added Test harness in both Sample Swift and Sample apps for iOS in order to test the plugin.
- Updated the documentation in `docs/shared-preferences-plugin.md` and` README.md`

I am open to suggestions since the desktop sharedPreferences version doesn't support deletion of preferences. Most likely I would have to modify the UI, and for that matter, I might as well build a user defaults desktop version

I wanted to add xiphirx in this MR since he developed the shared preferences plugin for Android and Desktop. I don't see a way to remove preferences from the flipper desktop app so I was wondering if you would be OK with me adding that.
Pull Request resolved: https://github.com/facebook/flipper/pull/291

Reviewed By: passy

Differential Revision: D10334685

Pulled By: priteshrnandgaonkar

fbshipit-source-id: d798c01a46df7ddecf713924799f046b560ea922
This commit is contained in:
Marc Terns
2018-10-12 04:07:39 -07:00
committed by Facebook Github Bot
parent 233b7bcd3c
commit c7ad49a9eb
21 changed files with 557 additions and 53 deletions

View File

@@ -46,6 +46,7 @@ This repository includes all parts of Flipper. This includes:
* Logs (`/src/device-plugins/logs`)
* Layout inspector (`/src/plugins/layout`)
* Network inspector (`/src/plugins/network`)
* Shared Preferences/NSUserDefaults inspector (`/src/plugins/shared_preferences`)
* website and documentation (`/website` / `/docs`)
# Getting started

View File

@@ -97,11 +97,12 @@ swift_version = "4.1"
flipperkit_version = '0.8.1'
target 'MyApp' do
platform :ios, '9.0'
pod 'FlipperKit', '~>'+flipperkit_version
# Layout and network plugins are not yet supported for swift projects
pod 'FlipperKit/FlipperKitLayoutComponentKitSupport', '~>' + flipperkit_version
pod 'FlipperKit/SKIOSNetworkPlugin', '~>' + flipperkit_version
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', '~>' + flipperkit_version
post_install do |installer|
@@ -120,6 +121,7 @@ and install the dependencies by running `pod install`. When you open the Xcode w
```objective-c
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
@implementation AppDelegate
@@ -130,6 +132,8 @@ and install the dependencies by running `pod install`. When you open the Xcode w
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode: application
withDescriptorMapper: layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client start];
#endif
...

View File

@@ -9,7 +9,7 @@ Easily inspect and modify the data contained within your app's shared preference
## Setup
Note: this plugin is only available for Android.
This plugin is available for both Android and iOS.
### Android
@@ -20,6 +20,24 @@ client.addPlugin(
new SharedPreferencesFlipperPlugin(context, "my_shared_preference_file"));
```
### iOS
#### Swift
```swift
import FlipperKit
client?.add(FKUserDefaultsPlugin.init(suiteName: "your_suitename"))
```
#### Objective-c
```objc
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:@"your_suitename"]];
```
## Usage
All changes to the given shared preference file will automatically appear in Flipper. You may also edit the values in Flipper and have them synced to your device. This can be done by clicking on the value of the specific key you wish to edit, editing the value and then pressing enter.

View File

@@ -63,6 +63,7 @@ Pod::Spec.new do |spec|
'iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKRequestInfo.h',
'iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKResponseInfo.h',
'iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h',
'iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h',
'iOS/FBDefines/FBMacros.h',
'iOS/FlipperKit/**/{FlipperStateUpdateListener,FlipperClient,FlipperPlugin,FlipperConnection,FlipperResponder,SKMacros}.h'
header_search_paths = "\"$(PODS_ROOT)/FlipperKit/iOS/FlipperKit\" \"$(PODS_ROOT)\"/Headers/Private/FlipperKit/** \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/PeerTalkSonar\""
@@ -131,4 +132,13 @@ Pod::Spec.new do |spec|
ss.source_files = "iOS/Plugins/FlipperKitNetworkPlugin/SKIOSNetworkPlugin/**/*.{h,cpp,m,mm}"
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)\"/Headers/Private/FlipperKit/**" }
end
spec.subspec "FlipperKitUserDefaultsPlugin" do |ss|
ss.header_dir = "FlipperKitUserDefaultsPlugin"
ss.dependency 'FlipperKit/Core'
ss.compiler_flags = folly_compiler_flags
ss.public_header_files = 'iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h'
ss.source_files = "iOS/Plugins/FlipperKitUserDefaultsPlugin/**/*.{h,m}"
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)\"/Headers/Private/FlipperKit/**" }
end
end

View File

@@ -0,0 +1,20 @@
//
// FKUserDefaultsPlugin.h
// Sample
//
// Created by Marc Terns on 9/30/18.
// Copyright © 2018 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <FlipperKit/FlipperPlugin.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKUserDefaultsPlugin : NSObject <FlipperPlugin>
- (instancetype)initWithSuiteName:(nullable NSString *)suiteName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,80 @@
//
// FKUserDefaultsPlugin.m
// Sample
//
// Created by Marc Terns on 9/30/18.
// Copyright © 2018 Facebook. All rights reserved.
//
#import "FKUserDefaultsPlugin.h"
#import <FlipperKit/FlipperConnection.h>
#import <FlipperKit/FlipperResponder.h>
#import "FKUserDefaultsSwizzleUtility.h"
@interface FKUserDefaultsPlugin ()
@property (nonatomic, strong) id<FlipperConnection> flipperConnection;
@property (nonatomic, strong) NSUserDefaults *userDefaults;
@property (nonatomic, copy) NSString *key;
@property (nonatomic, copy) NSString *suiteName;
@end
@implementation FKUserDefaultsPlugin
- (instancetype)initWithSuiteName:(NSString *)suiteName {
if (self = [super init]) {
_userDefaults = [NSUserDefaults standardUserDefaults];
_suiteName = suiteName;
__weak typeof(self) weakSelf = self;
[FKUserDefaultsSwizzleUtility swizzleSelector:@selector(setObject:forKey:) class:[NSUserDefaults class] block:^(NSInvocation * _Nonnull invocation) {
__unsafe_unretained id firstArg = nil;
__unsafe_unretained id secondArg = nil;
[invocation getArgument:&firstArg atIndex:2];
[invocation getArgument:&secondArg atIndex:3];
[invocation invoke];
[weakSelf userDefaultsChangedWithValue:firstArg key:secondArg];
}];
}
return self;
}
- (void)didConnect:(id<FlipperConnection>)connection {
self.flipperConnection = connection;
[connection receive:@"getSharedPreferences" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
[responder success:[self.userDefaults dictionaryRepresentation]];
}];
[connection receive:@"setSharedPreference" withBlock:^(NSDictionary *params , id<FlipperResponder> responder) {
NSString *preferenceName = params[@"preferenceName"];
[self.userDefaults setObject:params[@"preferenceValue"] forKey:preferenceName];
[responder success:[self.userDefaults dictionaryRepresentation]];
}];
}
- (void)didDisconnect {
self.flipperConnection = nil;
}
- (NSString *)identifier {
return @"Preferences";
}
#pragma mark - Private methods
- (void)userDefaultsChangedWithValue:(id)value key:(NSString *)key {
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
NSString *intervalStr = [NSString stringWithFormat:@"%f", interval];
NSMutableDictionary *params = [@{@"name":key,
@"time":intervalStr
} mutableCopy];
if (!value) {
[params setObject:@"YES" forKey:@"deleted"];
} else {
[params setObject:value forKey:@"value"];
}
[self.flipperConnection send:@"sharedPreferencesChange" withParams:[params copy]];
}
@end

View File

@@ -0,0 +1,18 @@
//
// FKUserDefaultsSwizzleUtility.h
// FlipperKit
//
// Created by Marc Terns on 10/6/18.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKUserDefaultsSwizzleUtility : NSObject
+ (void)swizzleSelector:(SEL)selector class:(Class)aClass block:(void(^)(NSInvocation *invocation))block;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,76 @@
//
// FKUserDefaultsSwizzleUtility.m
// FlipperKit
//
// Created by Marc Terns on 10/6/18.
//
#import "FKUserDefaultsSwizzleUtility.h"
#import <objc/runtime.h>
@interface FKUserDefaultsSwizzleUtility ()
@property (nonatomic, strong) NSMutableSet *swizzledClasses;
@property (nonatomic, strong) NSMutableDictionary *swizzledBlocks;
@property (nonatomic) IMP forwardingIMP;
@end
@implementation FKUserDefaultsSwizzleUtility
- (instancetype)init {
if (self = [super init]) {
_swizzledClasses = [NSMutableSet set];
_swizzledBlocks = [NSMutableDictionary dictionary];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
_forwardingIMP = class_getMethodImplementation([NSObject class], @selector(flipperKitThisMethodShouldNotExist));
#pragma clang diagnostic pop
}
return self;
}
+ (instancetype)sharedInstance {
static FKUserDefaultsSwizzleUtility *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
+ (void)swizzleSelector:(SEL)selector class:(Class)aClass block:(void (^)(NSInvocation * _Nonnull))block {
[[self sharedInstance] swizzleSelector:selector class:aClass block:block];
}
- (void)swizzleSelector:(SEL)selector class:(Class)aClass block:(void (^)(NSInvocation * _Nonnull))block {
if (![self.swizzledClasses containsObject:aClass]) {
SEL fwdSel = @selector(forwardInvocation:);
Method m = class_getInstanceMethod(aClass, fwdSel);
__block IMP orig;
__weak typeof(self) weakSelf = self;
IMP imp = imp_implementationWithBlock(^(id self, NSInvocation *invocation) {
NSString * selStr = NSStringFromSelector([invocation selector]);
void (^block)(NSInvocation *) = weakSelf.swizzledBlocks[aClass][selStr];
if (block != nil) {
NSString *originalStr = [@"comfacebookFlipperKit_" stringByAppendingString:selStr];
[invocation setSelector:NSSelectorFromString(originalStr)];
block(invocation);
} else {
((void (*)(id, SEL, NSInvocation *))orig)(self, fwdSel, invocation);
}
});
orig = method_setImplementation(m, imp);
[self.swizzledClasses addObject:aClass];
}
NSMutableDictionary *classDict = self.swizzledBlocks[aClass];
if (classDict == nil) {
classDict = [NSMutableDictionary dictionary];
self.swizzledBlocks[(id)aClass] = classDict;
}
classDict[NSStringFromSelector(selector)] = block;
Method m = class_getInstanceMethod(aClass, selector);
NSString *newSelStr = [@"comfacebookFlipperKit_" stringByAppendingString:NSStringFromSelector(selector)];
SEL newSel = NSSelectorFromString(newSelStr);
class_addMethod(aClass, newSel, method_getImplementation(m), method_getTypeEncoding(m));
method_setImplementation(m, self.forwardingIMP);
}
@end

View File

@@ -10,8 +10,10 @@
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitLayoutComponentKitSupport/FlipperKitLayoutComponentKitSupport.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import "MainViewController.h"
#import "RootViewController.h"
@@ -27,13 +29,14 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[FlipperKitLayoutComponentKitSupport setUpWithDescriptorMapper: layoutDescriptorMapper];
[client addPlugin: [[FlipperKitLayoutPlugin alloc] initWithRootNode: application
withDescriptorMapper: layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[[FlipperClient sharedClient] addPlugin: [[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -21,6 +21,20 @@
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sonarpattern" translatesAutoresizingMaskIntoConstraints="NO" id="B57-dd-H6T">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wdV-rw-8hy">
<rect key="frame" x="0.0" y="156" width="375" height="60"/>
<color key="backgroundColor" red="0.89411764709999997" green="0.87450980389999999" blue="0.92941176469999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="60" id="aj7-LU-dNw"/>
<constraint firstAttribute="height" constant="60" id="k5w-WD-ncV"/>
</constraints>
<state key="normal" title="User Defaults">
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="tappedUserDefaults:" destination="2r2-64-LPh" eventType="touchUpInside" id="c9s-hW-3Uc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="R0E-21-TJB">
<rect key="frame" x="0.0" y="20" width="375" height="60"/>
<color key="backgroundColor" red="0.89411764709999997" green="0.87450980389999999" blue="0.92941176469999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
@@ -53,12 +67,15 @@
<constraints>
<constraint firstItem="xh0-Q4-60g" firstAttribute="trailing" secondItem="fhd-5r-dZW" secondAttribute="trailing" id="0Uf-Hu-a0E"/>
<constraint firstItem="xh0-Q4-60g" firstAttribute="top" secondItem="R0E-21-TJB" secondAttribute="bottom" constant="8" id="1LN-rK-SJg"/>
<constraint firstItem="wdV-rw-8hy" firstAttribute="trailing" secondItem="xh0-Q4-60g" secondAttribute="trailing" id="3RQ-G9-NoU"/>
<constraint firstItem="R0E-21-TJB" firstAttribute="top" secondItem="fhd-5r-dZW" secondAttribute="top" id="4Og-b3-TDg"/>
<constraint firstItem="R0E-21-TJB" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="7mG-cL-FY7"/>
<constraint firstItem="xh0-Q4-60g" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="DPX-l5-Rca"/>
<constraint firstItem="B57-dd-H6T" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="Hhd-in-vfk"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="trailing" secondItem="B57-dd-H6T" secondAttribute="trailing" id="ODW-CJ-ean"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="trailing" secondItem="R0E-21-TJB" secondAttribute="trailing" id="QyG-ez-XwS"/>
<constraint firstItem="wdV-rw-8hy" firstAttribute="leading" secondItem="xh0-Q4-60g" secondAttribute="leading" id="ebs-Zh-KRL"/>
<constraint firstItem="wdV-rw-8hy" firstAttribute="top" secondItem="xh0-Q4-60g" secondAttribute="bottom" constant="8" id="g0a-Kf-scc"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="bottom" secondItem="B57-dd-H6T" secondAttribute="bottom" id="kh1-ra-tzR"/>
<constraint firstItem="B57-dd-H6T" firstAttribute="top" secondItem="fhd-5r-dZW" secondAttribute="top" id="vGA-oo-EGc"/>
</constraints>
@@ -158,8 +175,79 @@
</objects>
<point key="canvasLocation" x="958" y="280"/>
</scene>
<!--User Defaults View Controller-->
<scene sceneID="WTQ-n4-t3v">
<objects>
<viewController storyboardIdentifier="UserDefaultsViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="VHD-ba-abm" customClass="UserDefaultsViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="OCa-ry-ipe">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sonarpattern" translatesAutoresizingMaskIntoConstraints="NO" id="GgH-jO-sEF">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qPc-MG-653">
<rect key="frame" x="40" y="366" width="295" height="40"/>
<color key="backgroundColor" red="0.89411764709999997" green="0.87450980389999999" blue="0.92941176469999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="BcQ-Iy-Ybl"/>
<constraint firstAttribute="width" constant="295" id="TY0-ba-K8F"/>
</constraints>
<state key="normal" title="Save">
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="tappedGithubLitho:" destination="qMe-JX-czP" eventType="touchUpInside" id="wPi-ja-YXo"/>
<action selector="tappedSave:" destination="VHD-ba-abm" eventType="touchUpInside" id="cI3-q0-l2T"/>
</connections>
</button>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="key (cannot be nil)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="80Y-f6-kwl">
<rect key="frame" x="39.5" y="328.5" width="296" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="MFP-cm-uHZ"/>
<constraint firstAttribute="width" constant="296" id="qlF-Cu-akU"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="String Value..." textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="0At-MV-CVw">
<rect key="frame" x="40" y="290" width="295" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="8fO-qk-MZr"/>
<constraint firstAttribute="width" constant="295" id="LFW-DF-pnG"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="80Y-f6-kwl" firstAttribute="centerX" secondItem="GgH-jO-sEF" secondAttribute="centerX" id="2wS-MR-FU2"/>
<constraint firstItem="gSG-BS-ifN" firstAttribute="trailing" secondItem="GgH-jO-sEF" secondAttribute="trailing" id="9lu-H4-Ixo"/>
<constraint firstItem="80Y-f6-kwl" firstAttribute="centerY" secondItem="GgH-jO-sEF" secondAttribute="centerY" id="CBx-Gd-7cF"/>
<constraint firstItem="qPc-MG-653" firstAttribute="centerX" secondItem="GgH-jO-sEF" secondAttribute="centerX" id="HJN-8X-WMD"/>
<constraint firstItem="GgH-jO-sEF" firstAttribute="leading" secondItem="gSG-BS-ifN" secondAttribute="leading" id="Hva-Hn-bO6"/>
<constraint firstItem="0At-MV-CVw" firstAttribute="centerX" secondItem="GgH-jO-sEF" secondAttribute="centerX" id="Jzw-bv-6qe"/>
<constraint firstItem="80Y-f6-kwl" firstAttribute="top" secondItem="0At-MV-CVw" secondAttribute="bottom" constant="8.5" id="Vcg-1M-vMe"/>
<constraint firstItem="GgH-jO-sEF" firstAttribute="top" secondItem="gSG-BS-ifN" secondAttribute="top" id="ehP-nt-IdN"/>
<constraint firstItem="qPc-MG-653" firstAttribute="top" secondItem="80Y-f6-kwl" secondAttribute="bottom" constant="7.5" id="iTT-7c-IWW"/>
<constraint firstItem="gSG-BS-ifN" firstAttribute="bottom" secondItem="GgH-jO-sEF" secondAttribute="bottom" id="zLE-qV-P6N"/>
</constraints>
<viewLayoutGuide key="safeArea" id="gSG-BS-ifN"/>
</view>
<connections>
<outlet property="keyTextField" destination="80Y-f6-kwl" id="H6X-rN-dKc"/>
<outlet property="valueTextField" destination="0At-MV-CVw" id="QWP-LP-5nH"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="snT-Mu-i3U" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1613.5999999999999" y="278.41079460269867"/>
</scene>
</scenes>
<resources>
<image name="sonarpattern" width="421" height="658"/>
<image name="sonarpattern" width="843" height="1317"/>
</resources>
</document>

View File

@@ -10,6 +10,7 @@
#import "NetworkViewController.h"
#import "RootViewController.h"
#import "UserDefaultsViewController.h"
@interface MainViewController ()
@@ -35,4 +36,11 @@
[self.navigationController pushViewController:networkViewController animated:true];
}
- (IBAction)tappedUserDefaults:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryBoard" bundle:nil];
UserDefaultsViewController *userDefaultsViewController = [storyboard instantiateViewControllerWithIdentifier:@"UserDefaultsViewController"];
[self.navigationController pushViewController:userDefaultsViewController animated:true];
}
@end

View File

@@ -4,9 +4,11 @@ source 'https://github.com/CocoaPods/Specs'
swift_version = "4.1"
target 'Sample' do
platform :ios, '9.0'
pod 'FlipperKit', :path => '../../FlipperKit.podspec'
pod 'FlipperKit/FlipperKitLayoutComponentKitSupport', :path => '../../FlipperKit.podspec'
pod 'FlipperKit/SKIOSNetworkPlugin', :path => '../../FlipperKit.podspec'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', :path => '../../FlipperKit.podspec'
pod 'Flipper', :path => '../../Flipper.podspec'
post_install do |installer|

View File

@@ -7,7 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
070E4F377782060039511A32 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55478E5C767F9CC35112E1C9 /* libPods-Sample.a */; };
0D0B1CF0E859D91C55CC453B /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F97F4E8C3E28D8BFAAEE60F4 /* libPods-Sample.a */; };
4E102341216AD7B400160734 /* UserDefaultsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E102340216AD7B400160734 /* UserDefaultsViewController.m */; };
53D59DB320ABA18400207065 /* NetworkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D59DAA20ABA18300207065 /* NetworkViewController.m */; };
53D59DB420ABA18400207065 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 53D59DAB20ABA18300207065 /* AppDelegate.mm */; };
53D59DB520ABA18400207065 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D59DAD20ABA18300207065 /* MainViewController.m */; };
@@ -19,6 +20,8 @@
/* Begin PBXFileReference section */
081A9FC23643CD21C7D61AA1 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = "<group>"; };
4E10233F216AD7B400160734 /* UserDefaultsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserDefaultsViewController.h; sourceTree = "<group>"; };
4E102340216AD7B400160734 /* UserDefaultsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserDefaultsViewController.m; sourceTree = "<group>"; };
53D59DAA20ABA18300207065 /* NetworkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkViewController.m; sourceTree = SOURCE_ROOT; };
53D59DAB20ABA18300207065 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = SOURCE_ROOT; };
53D59DAC20ABA18300207065 /* NetworkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkViewController.h; sourceTree = SOURCE_ROOT; };
@@ -32,8 +35,8 @@
53E0DE4120ABA0E3005682E1 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
53E0DE5220ABA0E4005682E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
53E0DE5320ABA0E4005682E1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
55478E5C767F9CC35112E1C9 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
BDF8FF7C018FDB3437209993 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; };
F97F4E8C3E28D8BFAAEE60F4 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -41,7 +44,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
070E4F377782060039511A32 /* libPods-Sample.a in Frameworks */,
0D0B1CF0E859D91C55CC453B /* libPods-Sample.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -59,6 +62,8 @@
53D59DAD20ABA18300207065 /* MainViewController.m */,
53D59DAC20ABA18300207065 /* NetworkViewController.h */,
53D59DAA20ABA18300207065 /* NetworkViewController.m */,
4E10233F216AD7B400160734 /* UserDefaultsViewController.h */,
4E102340216AD7B400160734 /* UserDefaultsViewController.m */,
53D59DAE20ABA18300207065 /* RootViewController.h */,
53D59DAF20ABA18300207065 /* RootViewController.mm */,
53E0DE5220ABA0E4005682E1 /* Info.plist */,
@@ -97,7 +102,7 @@
C89232DD95E032B5B6FA95A1 /* Frameworks */ = {
isa = PBXGroup;
children = (
55478E5C767F9CC35112E1C9 /* libPods-Sample.a */,
F97F4E8C3E28D8BFAAEE60F4 /* libPods-Sample.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -194,6 +199,7 @@
buildActionMask = 2147483647;
files = (
53E0DE5420ABA0E4005682E1 /* main.m in Sources */,
4E102341216AD7B400160734 /* UserDefaultsViewController.m in Sources */,
53D59DB320ABA18400207065 /* NetworkViewController.m in Sources */,
53D59DB420ABA18400207065 /* AppDelegate.mm in Sources */,
53D59DB520ABA18400207065 /* MainViewController.m in Sources */,
@@ -342,7 +348,7 @@
"\"${PODS_ROOT}/Headers/Public/glog\"",
);
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.3;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -361,7 +367,7 @@
"-l\"DoubleConversion\"",
"-l\"Folly\"",
"-l\"PeerTalk\"",
"-l\"Flipper\"",
"-l\"Flipper\"",
"-l\"FlipperKit\"",
"-l\"Yoga\"",
"-l\"c++\"",
@@ -406,7 +412,7 @@
"\"${PODS_ROOT}/Headers/Public/glog\"",
);
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.3;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -425,7 +431,7 @@
"-l\"DoubleConversion\"",
"-l\"Folly\"",
"-l\"PeerTalk\"",
"-l\"Flipper\"",
"-l\"Flipper\"",
"-l\"FlipperKit\"",
"-l\"Yoga\"",
"-l\"c++\"",

View File

@@ -0,0 +1,17 @@
//
// UserDefaultsViewController.h
// Sample
//
// Created by Marc Terns on 10/7/18.
// Copyright © 2018 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UserDefaultsViewController : UIViewController
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,30 @@
//
// UserDefaultsViewController.m
// Sample
//
// Created by Marc Terns on 10/7/18.
// Copyright © 2018 Facebook. All rights reserved.
//
#import "UserDefaultsViewController.h"
@interface UserDefaultsViewController ()
@property (weak, nonatomic) IBOutlet UITextField *valueTextField;
@property (weak, nonatomic) IBOutlet UITextField *keyTextField;
@property (nonatomic, strong) NSUserDefaults *userDefaults;
@end
@implementation UserDefaultsViewController
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
_userDefaults = [[NSUserDefaults alloc] initWithSuiteName:nil];
}
return self;
}
- (IBAction)tappedSave:(id)sender {
[self.userDefaults setObject:self.valueTextField.text forKey:self.keyTextField.text];
}
@end

View File

@@ -4,9 +4,11 @@ source 'https://github.com/CocoaPods/Specs'
swift_version = "4.1"
target 'SampleSwift' do
platform :ios, '9.0'
pod 'Flipper', :path => '../../Flipper.podspec'
pod 'FlipperKit', :path => '../../FlipperKit.podspec'
pod 'FlipperKit/SKIOSNetworkPlugin', :path => '../../FlipperKit.podspec'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', :path => '../../FlipperKit.podspec'
# Layout and network plugins are not yet supported for swift projects
#pod 'SonarKit/FlipperKitLayoutComponentKitSupport', :path => '../../SonarKit.podspec'

View File

@@ -3,26 +3,28 @@ PODS:
- CocoaAsyncSocket (7.6.3)
- CocoaLibEvent (1.0.0)
- DoubleConversion (1.1.5)
- Flipper (0.7.2):
- Flipper (0.8.1):
- Folly (~> 1.1)
- RSocket (~> 0.10)
- FlipperKit (0.7.2):
- FlipperKit/Core (= 0.7.2)
- FlipperKit/Core (0.7.2):
- FlipperKit (0.8.1):
- FlipperKit/Core (= 0.8.1)
- FlipperKit/Core (0.8.1):
- CocoaAsyncSocket (~> 7.6)
- Flipper (~> 0.7.2)
- Flipper (~> 0.8.1)
- FlipperKit/CppBridge
- FlipperKit/FBCxxUtils
- FlipperKit/FBDefines
- Folly (~> 1.1)
- OpenSSL-Static (= 1.0.2.c1)
- PeerTalk (~> 0.0.2)
- FlipperKit/CppBridge (0.7.2)
- FlipperKit/FBCxxUtils (0.7.2)
- FlipperKit/FBDefines (0.7.2)
- FlipperKit/FlipperKitNetworkPlugin (0.7.2):
- FlipperKit/CppBridge (0.8.1)
- FlipperKit/FBCxxUtils (0.8.1)
- FlipperKit/FBDefines (0.8.1)
- FlipperKit/FlipperKitNetworkPlugin (0.8.1):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.7.2):
- FlipperKit/FlipperKitUserDefaultsPlugin (0.8.1):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.8.1):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (1.1.0):
@@ -40,6 +42,7 @@ PODS:
DEPENDENCIES:
- Flipper (from `../../Flipper.podspec`)
- FlipperKit (from `../../FlipperKit.podspec`)
- FlipperKit/FlipperKitUserDefaultsPlugin (from `../../FlipperKit.podspec`)
- FlipperKit/SKIOSNetworkPlugin (from `../../FlipperKit.podspec`)
SPEC REPOS:
@@ -50,7 +53,7 @@ SPEC REPOS:
- DoubleConversion
- glog
- OpenSSL-Static
https://github.com/facebook/Sonar.git:
https://github.com/facebook/Sonar:
- Folly
- PeerTalk
- RSocket
@@ -66,14 +69,14 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: eafaa68a7e0ec99ead0a7b35015e0bf25d2c8987
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: e22e0762848812a87afd67ffda3998d9ef29170c
Flipper: 495fbd327298fbc55b3ff7cb399eae52c1580494
FlipperKit: a3c03ff44340fa38ff476f6269484270533c5749
Flipper: 847a9ba40de727f6bb02a1b365674538f051ecf2
FlipperKit: 93c4d1c38f10ef2900f646ddb65c29bdf4975cfd
Folly: dd92f69322d8535b9df98d7c91e442b0fce2fff2
glog: 1de0bb937dccdc981596d3b5825ebfb765017ded
OpenSSL-Static: bd17e34564a8591ad76b740318683a6caa19a13e
PeerTalk: 77481b0a8136f226b90ccf828d6061f70139ffde
RSocket: 4fdb7e562db30a2d4fceddefdc601749ffc9ebe2
PODFILE CHECKSUM: 74eec891e5ca29c4d3817bc4c2c8ed86c6b9958c
PODFILE CHECKSUM: 3eeb7fcb7e93b388b33cfa6730390259dd6292f7
COCOAPODS: 1.5.3

View File

@@ -7,8 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
322121E8134CB1102F388691 /* libPods-SampleSwift.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6233B2BCBACBB2E8D715CC04 /* libPods-SampleSwift.a */; };
4E102343216ADB5900160734 /* UserDefaultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E102342216ADB5900160734 /* UserDefaultsViewController.swift */; };
532FF2DF211316ED00FC5A10 /* NetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532FF2DE211316ED00FC5A10 /* NetworkViewController.swift */; };
629899EF3F77DD9CC9462399 /* libPods-SampleSwift.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 54D075F591C612F4A46C4C50 /* libPods-SampleSwift.a */; };
A19C402720E20023004BF1F7 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A19C402620E20023004BF1F7 /* Icons.xcassets */; };
A1EC522D20DED61B007C6977 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EC522C20DED61B007C6977 /* AppDelegate.swift */; };
A1EC522F20DED61B007C6977 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EC522E20DED61B007C6977 /* ViewController.swift */; };
@@ -17,10 +18,11 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
4E102342216ADB5900160734 /* UserDefaultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsViewController.swift; sourceTree = "<group>"; };
532FF2DE211316ED00FC5A10 /* NetworkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkViewController.swift; sourceTree = "<group>"; };
54D075F591C612F4A46C4C50 /* libPods-SampleSwift.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleSwift.a"; sourceTree = BUILT_PRODUCTS_DIR; };
59BC319BD0C305C87CCBB954 /* Pods-SampleSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SampleSwift/Pods-SampleSwift.debug.xcconfig"; sourceTree = "<group>"; };
76A1EA0FA19A4343BF5468B9 /* Pods-SampleSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift.release.xcconfig"; path = "Pods/Target Support Files/Pods-SampleSwift/Pods-SampleSwift.release.xcconfig"; sourceTree = "<group>"; };
6233B2BCBACBB2E8D715CC04 /* libPods-SampleSwift.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleSwift.a"; sourceTree = BUILT_PRODUCTS_DIR; };
82933F6ACB19D9FAA4A0B0DC /* Pods-SampleSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift.release.xcconfig"; path = "Pods/Target Support Files/Pods-SampleSwift/Pods-SampleSwift.release.xcconfig"; sourceTree = "<group>"; };
871A353CDDB4CD0F4FE9A564 /* Pods-SampleSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SampleSwift/Pods-SampleSwift.debug.xcconfig"; sourceTree = "<group>"; };
A19C402620E20023004BF1F7 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = SOURCE_ROOT; };
A1EC522920DED61B007C6977 /* SampleSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleSwift.app; sourceTree = BUILT_PRODUCTS_DIR; };
A1EC522C20DED61B007C6977 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -35,20 +37,28 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
629899EF3F77DD9CC9462399 /* libPods-SampleSwift.a in Frameworks */,
322121E8134CB1102F388691 /* libPods-SampleSwift.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
690EC1830793DEC228432979 /* Frameworks */ = {
isa = PBXGroup;
children = (
6233B2BCBACBB2E8D715CC04 /* libPods-SampleSwift.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
A1EC522020DED61B007C6977 = {
isa = PBXGroup;
children = (
A1EC522B20DED61B007C6977 /* SampleSwift */,
A1EC522A20DED61B007C6977 /* Products */,
D64C1609A23F7F455EB46170 /* Pods */,
FCE001267EA01B99C44EBA11 /* Frameworks */,
B8EB61E9CA5FC85959AD5F3E /* Pods */,
690EC1830793DEC228432979 /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -70,27 +80,20 @@
A1EC523520DED61C007C6977 /* LaunchScreen.storyboard */,
A1EC523820DED61C007C6977 /* Info.plist */,
532FF2DE211316ED00FC5A10 /* NetworkViewController.swift */,
4E102342216ADB5900160734 /* UserDefaultsViewController.swift */,
);
path = SampleSwift;
sourceTree = "<group>";
};
D64C1609A23F7F455EB46170 /* Pods */ = {
B8EB61E9CA5FC85959AD5F3E /* Pods */ = {
isa = PBXGroup;
children = (
59BC319BD0C305C87CCBB954 /* Pods-SampleSwift.debug.xcconfig */,
76A1EA0FA19A4343BF5468B9 /* Pods-SampleSwift.release.xcconfig */,
871A353CDDB4CD0F4FE9A564 /* Pods-SampleSwift.debug.xcconfig */,
82933F6ACB19D9FAA4A0B0DC /* Pods-SampleSwift.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
FCE001267EA01B99C44EBA11 /* Frameworks */ = {
isa = PBXGroup;
children = (
54D075F591C612F4A46C4C50 /* libPods-SampleSwift.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -98,7 +101,7 @@
isa = PBXNativeTarget;
buildConfigurationList = A1EC523B20DED61C007C6977 /* Build configuration list for PBXNativeTarget "SampleSwift" */;
buildPhases = (
FEB6C3EADB1D3B088347CC11 /* [CP] Check Pods Manifest.lock */,
D9A91DD7C5294D8508D0A168 /* [CP] Check Pods Manifest.lock */,
A1EC522520DED61B007C6977 /* Sources */,
A1EC522620DED61B007C6977 /* Frameworks */,
A1EC522720DED61B007C6977 /* Resources */,
@@ -159,7 +162,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
FEB6C3EADB1D3B088347CC11 /* [CP] Check Pods Manifest.lock */ = {
D9A91DD7C5294D8508D0A168 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -186,6 +189,7 @@
files = (
A1EC522F20DED61B007C6977 /* ViewController.swift in Sources */,
532FF2DF211316ED00FC5A10 /* NetworkViewController.swift in Sources */,
4E102343216ADB5900160734 /* UserDefaultsViewController.swift in Sources */,
A1EC522D20DED61B007C6977 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -320,7 +324,7 @@
};
A1EC523C20DED61C007C6977 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 59BC319BD0C305C87CCBB954 /* Pods-SampleSwift.debug.xcconfig */;
baseConfigurationReference = 871A353CDDB4CD0F4FE9A564 /* Pods-SampleSwift.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -384,7 +388,7 @@
};
A1EC523D20DED61C007C6977 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 76A1EA0FA19A4343BF5468B9 /* Pods-SampleSwift.release.xcconfig */;
baseConfigurationReference = 82933F6ACB19D9FAA4A0B0DC /* Pods-SampleSwift.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;

View File

@@ -19,6 +19,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// client.addPlugin(FlipperKitLayoutPlugin(rootNode: application, descriptorMapper: layoutDescriptorMapper))
client?.add(FlipperKitNetworkPlugin(networkAdapter: SKIOSNetworkAdapter()))
client?.add(FKUserDefaultsPlugin.init(suiteName: nil))
client?.start()
let storyboard = UIStoryboard(name: "MainStoryBoard", bundle: nil)

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -45,17 +45,34 @@
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fNm-CZ-QXA">
<rect key="frame" x="0.0" y="156" width="375" height="60"/>
<color key="backgroundColor" red="0.89411764709999997" green="0.87450980389999999" blue="0.92941176469999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="60" id="npr-g6-NHN"/>
<constraint firstAttribute="height" constant="60" id="rC6-NM-7tF"/>
</constraints>
<state key="normal" title="User Defaults">
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<segue destination="qXL-iV-l3f" kind="show" id="ubf-Kh-d0a"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="xh0-Q4-60g" firstAttribute="trailing" secondItem="fhd-5r-dZW" secondAttribute="trailing" id="0Uf-Hu-a0E"/>
<constraint firstItem="xh0-Q4-60g" firstAttribute="top" secondItem="R0E-21-TJB" secondAttribute="bottom" constant="8" id="1LN-rK-SJg"/>
<constraint firstItem="fNm-CZ-QXA" firstAttribute="trailing" secondItem="xh0-Q4-60g" secondAttribute="trailing" id="4Dh-7z-set"/>
<constraint firstItem="R0E-21-TJB" firstAttribute="top" secondItem="fhd-5r-dZW" secondAttribute="top" id="4Og-b3-TDg"/>
<constraint firstItem="fNm-CZ-QXA" firstAttribute="leading" secondItem="xh0-Q4-60g" secondAttribute="leading" id="61y-q6-PKw"/>
<constraint firstItem="R0E-21-TJB" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="7mG-cL-FY7"/>
<constraint firstItem="xh0-Q4-60g" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="DPX-l5-Rca"/>
<constraint firstItem="B57-dd-H6T" firstAttribute="leading" secondItem="fhd-5r-dZW" secondAttribute="leading" id="Hhd-in-vfk"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="trailing" secondItem="B57-dd-H6T" secondAttribute="trailing" id="ODW-CJ-ean"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="trailing" secondItem="R0E-21-TJB" secondAttribute="trailing" id="QyG-ez-XwS"/>
<constraint firstItem="fNm-CZ-QXA" firstAttribute="top" secondItem="xh0-Q4-60g" secondAttribute="bottom" constant="8" id="jpH-cn-dRV"/>
<constraint firstItem="fhd-5r-dZW" firstAttribute="bottom" secondItem="B57-dd-H6T" secondAttribute="bottom" id="kh1-ra-tzR"/>
<constraint firstItem="B57-dd-H6T" firstAttribute="top" secondItem="fhd-5r-dZW" secondAttribute="top" id="vGA-oo-EGc"/>
</constraints>
@@ -156,8 +173,78 @@
</objects>
<point key="canvasLocation" x="958" y="280"/>
</scene>
<!--User Defaults View Controller-->
<scene sceneID="Lf5-Is-foC">
<objects>
<viewController storyboardIdentifier="UserDefaultsViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="qXL-iV-l3f" customClass="UserDefaultsViewController" customModule="SampleSwift" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="d4y-bZ-bMk">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sonarpattern" translatesAutoresizingMaskIntoConstraints="NO" id="NwP-P2-2qI">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mbW-th-h0H">
<rect key="frame" x="40" y="366" width="295" height="40"/>
<color key="backgroundColor" red="0.89411764709999997" green="0.87450980389999999" blue="0.92941176469999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="2Ck-uX-U8W"/>
<constraint firstAttribute="width" constant="295" id="Vm5-KP-Lin"/>
</constraints>
<state key="normal" title="Save">
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="tappedSave:" destination="qXL-iV-l3f" eventType="touchUpInside" id="2ny-9O-idj"/>
</connections>
</button>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="key (cannot be nil)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="th9-uR-BZx">
<rect key="frame" x="39.5" y="328.5" width="296" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="296" id="8Vb-8W-w9l"/>
<constraint firstAttribute="height" constant="30" id="Zt3-fY-1us"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="String Value..." textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="lZu-0P-qN9">
<rect key="frame" x="40" y="290" width="295" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="57Z-7r-viw"/>
<constraint firstAttribute="width" constant="295" id="9Ch-56-UaE"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="lZu-0P-qN9" firstAttribute="centerX" secondItem="NwP-P2-2qI" secondAttribute="centerX" id="8jU-Y6-In5"/>
<constraint firstItem="NwP-P2-2qI" firstAttribute="leading" secondItem="Tub-Io-dFp" secondAttribute="leading" id="CZ3-Tg-feY"/>
<constraint firstItem="mbW-th-h0H" firstAttribute="centerX" secondItem="NwP-P2-2qI" secondAttribute="centerX" id="EwC-G5-ovu"/>
<constraint firstItem="Tub-Io-dFp" firstAttribute="bottom" secondItem="NwP-P2-2qI" secondAttribute="bottom" id="Gu4-Iw-2FS"/>
<constraint firstItem="NwP-P2-2qI" firstAttribute="top" secondItem="Tub-Io-dFp" secondAttribute="top" id="Klq-9a-aCG"/>
<constraint firstItem="th9-uR-BZx" firstAttribute="centerY" secondItem="NwP-P2-2qI" secondAttribute="centerY" id="WSs-Qk-Ted"/>
<constraint firstItem="mbW-th-h0H" firstAttribute="top" secondItem="th9-uR-BZx" secondAttribute="bottom" constant="7.5" id="aJD-vA-qjO"/>
<constraint firstItem="th9-uR-BZx" firstAttribute="top" secondItem="lZu-0P-qN9" secondAttribute="bottom" constant="8.5" id="ky1-5U-S5x"/>
<constraint firstItem="th9-uR-BZx" firstAttribute="centerX" secondItem="NwP-P2-2qI" secondAttribute="centerX" id="yTa-ic-pLV"/>
<constraint firstItem="Tub-Io-dFp" firstAttribute="trailing" secondItem="NwP-P2-2qI" secondAttribute="trailing" id="zZm-qm-nCb"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Tub-Io-dFp"/>
</view>
<connections>
<outlet property="keyTextField" destination="th9-uR-BZx" id="Hye-pZ-fdM"/>
<outlet property="valueTextField" destination="lZu-0P-qN9" id="Fya-Kj-t0V"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Trg-qn-c4O" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1613.5999999999999" y="278.41079460269867"/>
</scene>
</scenes>
<resources>
<image name="sonarpattern" width="421" height="658"/>
<image name="sonarpattern" width="843" height="1317"/>
</resources>
</document>

View File

@@ -0,0 +1,26 @@
//
// UserDefaultsViewController.swift
// SampleSwift
//
// Created by Marc Terns on 10/7/18.
// Copyright © 2018 Noah Gilmore. All rights reserved.
//
import UIKit
class UserDefaultsViewController: UIViewController {
@IBOutlet weak var keyTextField: UITextField!
@IBOutlet weak var valueTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func tappedSave(_ sender: Any) {
UserDefaults.standard.set(self.valueTextField.text ?? "", forKey: self.keyTextField.text ?? "")
}
}