├── ContextCoreMLDemo
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── MyFirstCustomModel.mlmodel
├── Info.plist
├── AppDelegate.swift
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── ViewController.swift
├── SceneDelegate.swift
└── ModelDownloadManager.swift
├── docs
├── latest_model_details.json
└── models
│ ├── 40a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel
│ └── 80a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel
├── ContextCoreMLDemo.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── README.md
├── .gitignore
└── model_training.ipynb
/ContextCoreMLDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/MyFirstCustomModel.mlmodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KrauseFx/CoreMLDemo/HEAD/ContextCoreMLDemo/MyFirstCustomModel.mlmodel
--------------------------------------------------------------------------------
/docs/latest_model_details.json:
--------------------------------------------------------------------------------
1 | {
2 | "url": "https://krausefx.github.io/CoreMLDemo/models/80a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel"
3 | }
4 |
--------------------------------------------------------------------------------
/docs/models/40a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KrauseFx/CoreMLDemo/HEAD/docs/models/40a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel
--------------------------------------------------------------------------------
/docs/models/80a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KrauseFx/CoreMLDemo/HEAD/docs/models/80a2-82d1-bcf8-4ab5-9d35-d7f257c4c31e.mlmodel
--------------------------------------------------------------------------------
/ContextCoreMLDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is the demo app for distributing CoreML Machine Learning files over-the-air. For more context, check out [this post](https://contextsdk.com/blog/safely-distribute-new-machine-learning-models-to-millions-of-iphones-over-the-air)
2 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ContextCoreMLDemo
4 | //
5 | // Created by Felix Krause on 16.05.24.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/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 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import CoreML
3 |
4 | class ViewController: UIViewController {
5 | let modelDownloadManager = ModelDownloadManager()
6 |
7 | override func viewDidLoad() {
8 | super.viewDidLoad()
9 | }
10 |
11 | @IBAction func runLatestLocalModel() {
12 | let batteryLevel = UIDevice.current.batteryLevel
13 | let batteryCharging = UIDevice.current.batteryState == .charging || UIDevice.current.batteryState == .full
14 | do {
15 | let modelInput = MyFirstCustomModelInput(input: [
16 | Double(batteryLevel),
17 | Double(batteryCharging ? 1.0 : 0.0)
18 | ])
19 | if let currentModel = modelDownloadManager.latestModel(),
20 | let modelMetadata = currentModel.model.modelDescription.metadata[.description] {
21 | let result = try currentModel.prediction(input: modelInput)
22 | let classProbabilities = result.featureValue(for: "classProbability")?.dictionaryValue
23 | let upsellProbability = classProbabilities?["Purchased"]?.doubleValue ?? -1
24 |
25 | showAlertDialog(message:("Chances of Upsell: \(upsellProbability), executed through model \(String(describing: modelMetadata))"))
26 | } else {
27 | showAlertDialog(message:("Could not run CoreML model"))
28 | }
29 | } catch {
30 | showAlertDialog(message:("Error running CoreML file: \(error)"))
31 | }
32 | }
33 |
34 | @IBAction func downloadLatestModel() {
35 | Task {
36 | do {
37 | try await modelDownloadManager.checkForModelUpdates()
38 | showAlertDialog(message:("Model update completed successfully."))
39 | } catch {
40 | // Handle possible errors here
41 | showAlertDialog(message:("Failed to update model: \(error.localizedDescription)"))
42 | }
43 | }
44 | }
45 |
46 | internal func showAlertDialog(message: String) {
47 | let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
48 | alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
49 | self.present(alert, animated: true, completion: nil)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // ContextCoreMLDemo
4 | //
5 | // Created by Felix Krause on 16.05.24.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_STORE
2 |
3 | # Xcode
4 | #
5 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
6 |
7 | ## User settings
8 | xcuserdata/
9 |
10 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
11 | *.xcscmblueprint
12 | *.xccheckout
13 |
14 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
15 | build/
16 | DerivedData/
17 | *.moved-aside
18 | *.pbxuser
19 | !default.pbxuser
20 | *.mode1v3
21 | !default.mode1v3
22 | *.mode2v3
23 | !default.mode2v3
24 | *.perspectivev3
25 | !default.perspectivev3
26 |
27 | ## Obj-C/Swift specific
28 | *.hmap
29 |
30 | ## App packaging
31 | *.ipa
32 | *.dSYM.zip
33 | *.dSYM
34 |
35 | ## Playgrounds
36 | timeline.xctimeline
37 | playground.xcworkspace
38 |
39 | # Swift Package Manager
40 | #
41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
42 | # Packages/
43 | # Package.pins
44 | # Package.resolved
45 | # *.xcodeproj
46 | #
47 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
48 | # hence it is not needed unless you have added a package configuration file to your project
49 | # .swiftpm
50 |
51 | .build/
52 |
53 | # CocoaPods
54 | #
55 | # We recommend against adding the Pods directory to your .gitignore. However
56 | # you should judge for yourself, the pros and cons are mentioned at:
57 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
58 | #
59 | # Pods/
60 | #
61 | # Add this line if you want to avoid checking in source code from the Xcode workspace
62 | # *.xcworkspace
63 |
64 | # Carthage
65 | #
66 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
67 | # Carthage/Checkouts
68 |
69 | Carthage/Build/
70 |
71 | # Accio dependency management
72 | Dependencies/
73 | .accio/
74 |
75 | # fastlane
76 | #
77 | # It is recommended to not store the screenshots in the git repo.
78 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
79 | # For more information about the recommended setup visit:
80 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
81 |
82 | fastlane/report.xml
83 | fastlane/Preview.html
84 | fastlane/screenshots/**/*.png
85 | fastlane/test_output
86 |
87 | # Code Injection
88 | #
89 | # After new code Injection tools there's a generated folder /iOSInjectionProject
90 | # https://github.com/johnno1962/injectionforxcode
91 |
92 | iOSInjectionProject/
93 |
94 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
28 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo/ModelDownloadManager.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import CoreML
3 |
4 | class ModelDownloadManager {
5 | private let fileManager: FileManager
6 | private let modelsFolder: URL
7 | private let modelUpdateCheckURL = "https://krausefx.github.io/CoreMLDemo/latest_model_details.json"
8 |
9 | init(fileManager: FileManager = .default) {
10 | self.fileManager = fileManager
11 | if let folder = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first?.appendingPathComponent("context_sdk_models") {
12 | self.modelsFolder = folder
13 | try? fileManager.createDirectory(at: folder, withIntermediateDirectories: true)
14 | } else {
15 | fatalError("Unable to find or create models folder.") // Handle this more gracefully
16 | }
17 | }
18 |
19 | internal func latestModel() -> MyFirstCustomModel? {
20 | let fileManagerContents = (try? fileManager.contentsOfDirectory(at: modelsFolder, includingPropertiesForKeys: nil)) ?? []
21 |
22 | // Try to find the latest model file based on modification date
23 | if let latestFileURL = fileManagerContents.sorted(by: { $0.lastPathComponent > $1.lastPathComponent }).first,
24 | let otaModel = try? MyFirstCustomModel(contentsOf: latestFileURL) {
25 | return otaModel
26 | } else if let bundledModel = try? MyFirstCustomModel(configuration: MLModelConfiguration()) {
27 | return bundledModel // Fallback to the bundled model if no downloaded model exists
28 | }
29 | return nil
30 | }
31 |
32 | internal func checkForModelUpdates() async throws {
33 | guard let url = URL(string: modelUpdateCheckURL) else {
34 | throw URLError(.badURL)
35 | }
36 | let (data, _) = try await URLSession.shared.data(from: url)
37 | guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any],
38 | let modelDownloadURLString = jsonObject["url"] as? String,
39 | let modelDownloadURL = URL(string: modelDownloadURLString) else {
40 | throw URLError(.cannotParseResponse)
41 | }
42 |
43 | try await downloadIfNeeded(from: modelDownloadURL)
44 | }
45 |
46 | private func downloadIfNeeded(from url: URL) async throws {
47 | let lastPathComponent = url.lastPathComponent
48 |
49 | // Check if the model file already exists (for this sample project we use the unique file name as identifier)
50 | if let localFiles = try? fileManager.contentsOfDirectory(at: modelsFolder, includingPropertiesForKeys: nil),
51 | localFiles.contains(where: { $0.lastPathComponent == lastPathComponent }) {
52 | // File exists, you could add a version check here if versions are part of the file name or metadata
53 | print("Model already exists locally. No need to download.")
54 | } else {
55 | let downloadedURL = try await downloadCoreMLFile(from: url) // File does not exist, download it
56 | let compiledURL = try compileCoreMLFile(at: downloadedURL)
57 | try deleteAllOutdatedModels(keeping: compiledURL.lastPathComponent)
58 | print("Model downloaded, compiled, and old models cleaned up successfully.")
59 | }
60 | }
61 |
62 | // It's important to immediately move the downloaded CoreML file into a permanent location
63 | private func downloadCoreMLFile(from url: URL) async throws -> URL {
64 | let (tempLocalURL, _) = try await URLSession.shared.download(for: URLRequest(url: url))
65 | let destinationURL = modelsFolder.appendingPathComponent(tempLocalURL.lastPathComponent)
66 | try fileManager.moveItem(at: tempLocalURL, to: destinationURL)
67 | return destinationURL
68 | }
69 |
70 | private func compileCoreMLFile(at localFilePath: URL) throws -> URL {
71 | let compiledModelURL = try MLModel.compileModel(at: localFilePath)
72 | let destinationCompiledURL = modelsFolder.appendingPathComponent(compiledModelURL.lastPathComponent)
73 | try fileManager.moveItem(at: compiledModelURL, to: destinationCompiledURL)
74 | try fileManager.removeItem(at: localFilePath)
75 | return destinationCompiledURL
76 | }
77 |
78 | private func deleteAllOutdatedModels(keeping recentModelFileName: String) throws {
79 | let urlContent = try fileManager.contentsOfDirectory(at: modelsFolder, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
80 | for fileURL in urlContent where fileURL.lastPathComponent != recentModelFileName {
81 | try fileManager.removeItem(at: fileURL)
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/model_training.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 8,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stdout",
10 | "output_type": "stream",
11 | "text": [
12 | " Outcome Battery Level Phone Charging?\n",
13 | "0 Dismissed 0.90 False\n",
14 | "1 Dismissed 0.10 False\n",
15 | "2 Purchased 0.24 True\n",
16 | "3 Dismissed 0.13 True\n",
17 | "4 Purchased 0.94 True\n"
18 | ]
19 | }
20 | ],
21 | "source": [
22 | "import pandas as pd\n",
23 | "\n",
24 | "rows = [\n",
25 | " ['Dismissed', 0.90, False],\n",
26 | " ['Dismissed', 0.10, False],\n",
27 | " ['Purchased', 0.24, True],\n",
28 | " ['Dismissed', 0.13, True],\n",
29 | " ['Purchased', 0.94, True],\n",
30 | " ['Dismissed', 0.11, False],\n",
31 | " ['Purchased', 0.89, True],\n",
32 | " ['Dismissed', 0.06, False],\n",
33 | " ['Purchased', 0.76, True],\n",
34 | " ['Dismissed', 0.22, False],\n",
35 | " ['Purchased', 0.91, True],\n",
36 | " ['Dismissed', 0.05, False],\n",
37 | " ['Purchased', 0.83, True],\n",
38 | " ['Dismissed', 0.14, False],\n",
39 | " ['Purchased', 0.92, True],\n",
40 | " ['Dismissed', 0.08, False],\n",
41 | " ['Purchased', 0.88, True],\n",
42 | " ['Dismissed', 0.18, False],\n",
43 | " ['Purchased', 0.93, True],\n",
44 | " ['Dismissed', 0.07, False],\n",
45 | " ['Purchased', 0.85, True],\n",
46 | " ['Dismissed', 0.13, False],\n",
47 | " ['Purchased', 0.90, True],\n",
48 | " ['Dismissed', 0.10, False],\n",
49 | " ['Purchased', 0.84, True],\n",
50 | " ['Dismissed', 0.16, False],\n",
51 | " ['Purchased', 0.91, True],\n",
52 | " ['Dismissed', 0.09, False],\n",
53 | " ['Purchased', 0.86, True],\n",
54 | " ['Dismissed', 0.14, False],\n",
55 | " ['Purchased', 0.95, True],\n",
56 | " ['Dismissed', 0.05, False],\n",
57 | " ['Purchased', 0.82, True],\n",
58 | " ['Dismissed', 0.18, False],\n",
59 | " ['Purchased', 0.93, True],\n",
60 | " ['Dismissed', 0.07, False],\n",
61 | " ['Purchased', 0.87, True],\n",
62 | " ['Dismissed', 0.13, False],\n",
63 | " ['Purchased', 0.90, True],\n",
64 | " ['Dismissed', 0.10, False],\n",
65 | " ['Purchased', 0.84, True],\n",
66 | " ['Dismissed', 0.16, False],\n",
67 | " ['Purchased', 0.92, True],\n",
68 | " ['Dismissed', 0.08, False],\n",
69 | " ['Purchased', 0.88, True],\n",
70 | " ['Dismissed', 0.12, False],\n",
71 | " ['Purchased', 0.91, True],\n",
72 | " ['Dismissed', 0.09, False],\n",
73 | " ['Purchased', 0.86, True],\n",
74 | " ['Dismissed', 0.14, False],\n",
75 | " ['Purchased', 0.94, True],\n",
76 | " ['Dismissed', 0.06, False]\n",
77 | "]\n",
78 | "data = pd.DataFrame(rows, columns=['Outcome', 'Battery Level', 'Phone Charging?'])\n",
79 | "print(data.head(5))"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": 9,
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "from sklearn.model_selection import train_test_split\n",
89 | "\n",
90 | "X = data.drop(\"Outcome\", axis=1)\n",
91 | "Y = data[\"Outcome\"]\n",
92 | "\n",
93 | "X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, shuffle=True)\n"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 10,
99 | "metadata": {},
100 | "outputs": [
101 | {
102 | "name": "stdout",
103 | "output_type": "stream",
104 | "text": [
105 | " precision recall f1-score support\n",
106 | "\n",
107 | " Dismissed 1.00 1.00 1.00 5\n",
108 | " Purchased 1.00 1.00 1.00 6\n",
109 | "\n",
110 | " accuracy 1.00 11\n",
111 | " macro avg 1.00 1.00 1.00 11\n",
112 | "weighted avg 1.00 1.00 1.00 11\n",
113 | "\n"
114 | ]
115 | }
116 | ],
117 | "source": [
118 | "from sklearn.ensemble import RandomForestClassifier\n",
119 | "from sklearn.metrics import classification_report\n",
120 | "\n",
121 | "classifier = RandomForestClassifier()\n",
122 | "classifier.fit(X_train, Y_train)\n",
123 | "Y_pred = classifier.predict(X_test)\n",
124 | "print(classification_report(Y_test, Y_pred, zero_division=1))"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 11,
130 | "metadata": {},
131 | "outputs": [
132 | {
133 | "name": "stderr",
134 | "output_type": "stream",
135 | "text": [
136 | "/Users/krausefx/Library/Python/3.9/lib/python/site-packages/sklearn/utils/deprecation.py:103: FutureWarning: Attribute `n_features_` was deprecated in version 1.0 and will be removed in 1.2. Use `n_features_in_` instead.\n",
137 | " warnings.warn(msg, category=FutureWarning)\n"
138 | ]
139 | }
140 | ],
141 | "source": [
142 | "import coremltools\n",
143 | "\n",
144 | "coreml_model = coremltools.converters.sklearn.convert(classifier, input_features=\"input\")\n",
145 | "coreml_model.short_description = \"My first model\"\n",
146 | "coreml_model.save(\"ContextCoreMLDemo/MyFirstCustomModel.mlmodel\")"
147 | ]
148 | }
149 | ],
150 | "metadata": {
151 | "kernelspec": {
152 | "display_name": "Python 3",
153 | "language": "python",
154 | "name": "python3"
155 | },
156 | "language_info": {
157 | "codemirror_mode": {
158 | "name": "ipython",
159 | "version": 3
160 | },
161 | "file_extension": ".py",
162 | "mimetype": "text/x-python",
163 | "name": "python",
164 | "nbconvert_exporter": "python",
165 | "pygments_lexer": "ipython3",
166 | "version": "3.9.6"
167 | }
168 | },
169 | "nbformat": 4,
170 | "nbformat_minor": 2
171 | }
172 |
--------------------------------------------------------------------------------
/ContextCoreMLDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | F20732362BF5ECD3002F3A39 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F20732352BF5ECD3002F3A39 /* AppDelegate.swift */; };
11 | F20732382BF5ECD3002F3A39 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F20732372BF5ECD3002F3A39 /* SceneDelegate.swift */; };
12 | F207323A2BF5ECD3002F3A39 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F20732392BF5ECD3002F3A39 /* ViewController.swift */; };
13 | F207323D2BF5ECD4002F3A39 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = F207323C2BF5ECD4002F3A39 /* Base */; };
14 | F207323F2BF5ECD5002F3A39 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F207323E2BF5ECD5002F3A39 /* Assets.xcassets */; };
15 | F20732422BF5ECD5002F3A39 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = F20732412BF5ECD5002F3A39 /* Base */; };
16 | F207324C2BF5EFFF002F3A39 /* MyFirstCustomModel.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = F207324B2BF5EFFF002F3A39 /* MyFirstCustomModel.mlmodel */; };
17 | F207324E2BF61B73002F3A39 /* ModelDownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F207324D2BF61B73002F3A39 /* ModelDownloadManager.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | F20732322BF5ECD3002F3A39 /* ContextCoreMLDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ContextCoreMLDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | F20732352BF5ECD3002F3A39 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
23 | F20732372BF5ECD3002F3A39 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
24 | F20732392BF5ECD3002F3A39 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | F207323C2BF5ECD4002F3A39 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | F207323E2BF5ECD5002F3A39 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | F20732412BF5ECD5002F3A39 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | F20732432BF5ECD5002F3A39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | F207324B2BF5EFFF002F3A39 /* MyFirstCustomModel.mlmodel */ = {isa = PBXFileReference; lastKnownFileType = file.mlmodel; path = MyFirstCustomModel.mlmodel; sourceTree = ""; };
30 | F207324D2BF61B73002F3A39 /* ModelDownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelDownloadManager.swift; sourceTree = ""; };
31 | /* End PBXFileReference section */
32 |
33 | /* Begin PBXFrameworksBuildPhase section */
34 | F207322F2BF5ECD3002F3A39 /* Frameworks */ = {
35 | isa = PBXFrameworksBuildPhase;
36 | buildActionMask = 2147483647;
37 | files = (
38 | );
39 | runOnlyForDeploymentPostprocessing = 0;
40 | };
41 | /* End PBXFrameworksBuildPhase section */
42 |
43 | /* Begin PBXGroup section */
44 | F20732292BF5ECD3002F3A39 = {
45 | isa = PBXGroup;
46 | children = (
47 | F20732342BF5ECD3002F3A39 /* ContextCoreMLDemo */,
48 | F20732332BF5ECD3002F3A39 /* Products */,
49 | );
50 | sourceTree = "";
51 | };
52 | F20732332BF5ECD3002F3A39 /* Products */ = {
53 | isa = PBXGroup;
54 | children = (
55 | F20732322BF5ECD3002F3A39 /* ContextCoreMLDemo.app */,
56 | );
57 | name = Products;
58 | sourceTree = "";
59 | };
60 | F20732342BF5ECD3002F3A39 /* ContextCoreMLDemo */ = {
61 | isa = PBXGroup;
62 | children = (
63 | F20732352BF5ECD3002F3A39 /* AppDelegate.swift */,
64 | F20732372BF5ECD3002F3A39 /* SceneDelegate.swift */,
65 | F20732392BF5ECD3002F3A39 /* ViewController.swift */,
66 | F207323B2BF5ECD4002F3A39 /* Main.storyboard */,
67 | F207323E2BF5ECD5002F3A39 /* Assets.xcassets */,
68 | F20732402BF5ECD5002F3A39 /* LaunchScreen.storyboard */,
69 | F20732432BF5ECD5002F3A39 /* Info.plist */,
70 | F207324B2BF5EFFF002F3A39 /* MyFirstCustomModel.mlmodel */,
71 | F207324D2BF61B73002F3A39 /* ModelDownloadManager.swift */,
72 | );
73 | path = ContextCoreMLDemo;
74 | sourceTree = "";
75 | };
76 | /* End PBXGroup section */
77 |
78 | /* Begin PBXNativeTarget section */
79 | F20732312BF5ECD3002F3A39 /* ContextCoreMLDemo */ = {
80 | isa = PBXNativeTarget;
81 | buildConfigurationList = F20732462BF5ECD5002F3A39 /* Build configuration list for PBXNativeTarget "ContextCoreMLDemo" */;
82 | buildPhases = (
83 | F207322E2BF5ECD3002F3A39 /* Sources */,
84 | F207322F2BF5ECD3002F3A39 /* Frameworks */,
85 | F20732302BF5ECD3002F3A39 /* Resources */,
86 | );
87 | buildRules = (
88 | );
89 | dependencies = (
90 | );
91 | name = ContextCoreMLDemo;
92 | productName = ContextCoreMLDemo;
93 | productReference = F20732322BF5ECD3002F3A39 /* ContextCoreMLDemo.app */;
94 | productType = "com.apple.product-type.application";
95 | };
96 | /* End PBXNativeTarget section */
97 |
98 | /* Begin PBXProject section */
99 | F207322A2BF5ECD3002F3A39 /* Project object */ = {
100 | isa = PBXProject;
101 | attributes = {
102 | BuildIndependentTargetsInParallel = 1;
103 | LastSwiftUpdateCheck = 1540;
104 | LastUpgradeCheck = 1540;
105 | TargetAttributes = {
106 | F20732312BF5ECD3002F3A39 = {
107 | CreatedOnToolsVersion = 15.4;
108 | };
109 | };
110 | };
111 | buildConfigurationList = F207322D2BF5ECD3002F3A39 /* Build configuration list for PBXProject "ContextCoreMLDemo" */;
112 | compatibilityVersion = "Xcode 14.0";
113 | developmentRegion = en;
114 | hasScannedForEncodings = 0;
115 | knownRegions = (
116 | en,
117 | Base,
118 | );
119 | mainGroup = F20732292BF5ECD3002F3A39;
120 | productRefGroup = F20732332BF5ECD3002F3A39 /* Products */;
121 | projectDirPath = "";
122 | projectRoot = "";
123 | targets = (
124 | F20732312BF5ECD3002F3A39 /* ContextCoreMLDemo */,
125 | );
126 | };
127 | /* End PBXProject section */
128 |
129 | /* Begin PBXResourcesBuildPhase section */
130 | F20732302BF5ECD3002F3A39 /* Resources */ = {
131 | isa = PBXResourcesBuildPhase;
132 | buildActionMask = 2147483647;
133 | files = (
134 | F207323F2BF5ECD5002F3A39 /* Assets.xcassets in Resources */,
135 | F20732422BF5ECD5002F3A39 /* Base in Resources */,
136 | F207323D2BF5ECD4002F3A39 /* Base in Resources */,
137 | );
138 | runOnlyForDeploymentPostprocessing = 0;
139 | };
140 | /* End PBXResourcesBuildPhase section */
141 |
142 | /* Begin PBXSourcesBuildPhase section */
143 | F207322E2BF5ECD3002F3A39 /* Sources */ = {
144 | isa = PBXSourcesBuildPhase;
145 | buildActionMask = 2147483647;
146 | files = (
147 | F207324C2BF5EFFF002F3A39 /* MyFirstCustomModel.mlmodel in Sources */,
148 | F207324E2BF61B73002F3A39 /* ModelDownloadManager.swift in Sources */,
149 | F207323A2BF5ECD3002F3A39 /* ViewController.swift in Sources */,
150 | F20732362BF5ECD3002F3A39 /* AppDelegate.swift in Sources */,
151 | F20732382BF5ECD3002F3A39 /* SceneDelegate.swift in Sources */,
152 | );
153 | runOnlyForDeploymentPostprocessing = 0;
154 | };
155 | /* End PBXSourcesBuildPhase section */
156 |
157 | /* Begin PBXVariantGroup section */
158 | F207323B2BF5ECD4002F3A39 /* Main.storyboard */ = {
159 | isa = PBXVariantGroup;
160 | children = (
161 | F207323C2BF5ECD4002F3A39 /* Base */,
162 | );
163 | name = Main.storyboard;
164 | sourceTree = "";
165 | };
166 | F20732402BF5ECD5002F3A39 /* LaunchScreen.storyboard */ = {
167 | isa = PBXVariantGroup;
168 | children = (
169 | F20732412BF5ECD5002F3A39 /* Base */,
170 | );
171 | name = LaunchScreen.storyboard;
172 | sourceTree = "";
173 | };
174 | /* End PBXVariantGroup section */
175 |
176 | /* Begin XCBuildConfiguration section */
177 | F20732442BF5ECD5002F3A39 /* Debug */ = {
178 | isa = XCBuildConfiguration;
179 | buildSettings = {
180 | ALWAYS_SEARCH_USER_PATHS = NO;
181 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
182 | CLANG_ANALYZER_NONNULL = YES;
183 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
184 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
185 | CLANG_ENABLE_MODULES = YES;
186 | CLANG_ENABLE_OBJC_ARC = YES;
187 | CLANG_ENABLE_OBJC_WEAK = YES;
188 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
189 | CLANG_WARN_BOOL_CONVERSION = YES;
190 | CLANG_WARN_COMMA = YES;
191 | CLANG_WARN_CONSTANT_CONVERSION = YES;
192 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
194 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
195 | CLANG_WARN_EMPTY_BODY = YES;
196 | CLANG_WARN_ENUM_CONVERSION = YES;
197 | CLANG_WARN_INFINITE_RECURSION = YES;
198 | CLANG_WARN_INT_CONVERSION = YES;
199 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
200 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
201 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
202 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
203 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
204 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
205 | CLANG_WARN_STRICT_PROTOTYPES = YES;
206 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
207 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
208 | CLANG_WARN_UNREACHABLE_CODE = YES;
209 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
210 | COPY_PHASE_STRIP = NO;
211 | DEBUG_INFORMATION_FORMAT = dwarf;
212 | ENABLE_STRICT_OBJC_MSGSEND = YES;
213 | ENABLE_TESTABILITY = YES;
214 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
215 | GCC_C_LANGUAGE_STANDARD = gnu17;
216 | GCC_DYNAMIC_NO_PIC = NO;
217 | GCC_NO_COMMON_BLOCKS = YES;
218 | GCC_OPTIMIZATION_LEVEL = 0;
219 | GCC_PREPROCESSOR_DEFINITIONS = (
220 | "DEBUG=1",
221 | "$(inherited)",
222 | );
223 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
224 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
225 | GCC_WARN_UNDECLARED_SELECTOR = YES;
226 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
227 | GCC_WARN_UNUSED_FUNCTION = YES;
228 | GCC_WARN_UNUSED_VARIABLE = YES;
229 | IPHONEOS_DEPLOYMENT_TARGET = 17.5;
230 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
231 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
232 | MTL_FAST_MATH = YES;
233 | ONLY_ACTIVE_ARCH = YES;
234 | SDKROOT = iphoneos;
235 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
236 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
237 | };
238 | name = Debug;
239 | };
240 | F20732452BF5ECD5002F3A39 /* Release */ = {
241 | isa = XCBuildConfiguration;
242 | buildSettings = {
243 | ALWAYS_SEARCH_USER_PATHS = NO;
244 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
245 | CLANG_ANALYZER_NONNULL = YES;
246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
248 | CLANG_ENABLE_MODULES = YES;
249 | CLANG_ENABLE_OBJC_ARC = YES;
250 | CLANG_ENABLE_OBJC_WEAK = YES;
251 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
252 | CLANG_WARN_BOOL_CONVERSION = YES;
253 | CLANG_WARN_COMMA = YES;
254 | CLANG_WARN_CONSTANT_CONVERSION = YES;
255 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
256 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
257 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
258 | CLANG_WARN_EMPTY_BODY = YES;
259 | CLANG_WARN_ENUM_CONVERSION = YES;
260 | CLANG_WARN_INFINITE_RECURSION = YES;
261 | CLANG_WARN_INT_CONVERSION = YES;
262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
266 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
267 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
268 | CLANG_WARN_STRICT_PROTOTYPES = YES;
269 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
270 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
271 | CLANG_WARN_UNREACHABLE_CODE = YES;
272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
273 | COPY_PHASE_STRIP = NO;
274 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
275 | ENABLE_NS_ASSERTIONS = NO;
276 | ENABLE_STRICT_OBJC_MSGSEND = YES;
277 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
278 | GCC_C_LANGUAGE_STANDARD = gnu17;
279 | GCC_NO_COMMON_BLOCKS = YES;
280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
282 | GCC_WARN_UNDECLARED_SELECTOR = YES;
283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
284 | GCC_WARN_UNUSED_FUNCTION = YES;
285 | GCC_WARN_UNUSED_VARIABLE = YES;
286 | IPHONEOS_DEPLOYMENT_TARGET = 17.5;
287 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
288 | MTL_ENABLE_DEBUG_INFO = NO;
289 | MTL_FAST_MATH = YES;
290 | SDKROOT = iphoneos;
291 | SWIFT_COMPILATION_MODE = wholemodule;
292 | VALIDATE_PRODUCT = YES;
293 | };
294 | name = Release;
295 | };
296 | F20732472BF5ECD5002F3A39 /* Debug */ = {
297 | isa = XCBuildConfiguration;
298 | buildSettings = {
299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
300 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
301 | CODE_SIGN_STYLE = Automatic;
302 | CURRENT_PROJECT_VERSION = 1;
303 | DEVELOPMENT_TEAM = 35BGN5XEU6;
304 | GENERATE_INFOPLIST_FILE = YES;
305 | INFOPLIST_FILE = ContextCoreMLDemo/Info.plist;
306 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
307 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
308 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
309 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
310 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
311 | LD_RUNPATH_SEARCH_PATHS = (
312 | "$(inherited)",
313 | "@executable_path/Frameworks",
314 | );
315 | MARKETING_VERSION = 1.0;
316 | PRODUCT_BUNDLE_IDENTIFIER = com.contextsdk.ContextCoreMLDemo;
317 | PRODUCT_NAME = "$(TARGET_NAME)";
318 | SWIFT_EMIT_LOC_STRINGS = YES;
319 | SWIFT_VERSION = 5.0;
320 | TARGETED_DEVICE_FAMILY = "1,2";
321 | };
322 | name = Debug;
323 | };
324 | F20732482BF5ECD5002F3A39 /* Release */ = {
325 | isa = XCBuildConfiguration;
326 | buildSettings = {
327 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
328 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
329 | CODE_SIGN_STYLE = Automatic;
330 | CURRENT_PROJECT_VERSION = 1;
331 | DEVELOPMENT_TEAM = 35BGN5XEU6;
332 | GENERATE_INFOPLIST_FILE = YES;
333 | INFOPLIST_FILE = ContextCoreMLDemo/Info.plist;
334 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
335 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
336 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
337 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
338 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
339 | LD_RUNPATH_SEARCH_PATHS = (
340 | "$(inherited)",
341 | "@executable_path/Frameworks",
342 | );
343 | MARKETING_VERSION = 1.0;
344 | PRODUCT_BUNDLE_IDENTIFIER = com.contextsdk.ContextCoreMLDemo;
345 | PRODUCT_NAME = "$(TARGET_NAME)";
346 | SWIFT_EMIT_LOC_STRINGS = YES;
347 | SWIFT_VERSION = 5.0;
348 | TARGETED_DEVICE_FAMILY = "1,2";
349 | };
350 | name = Release;
351 | };
352 | /* End XCBuildConfiguration section */
353 |
354 | /* Begin XCConfigurationList section */
355 | F207322D2BF5ECD3002F3A39 /* Build configuration list for PBXProject "ContextCoreMLDemo" */ = {
356 | isa = XCConfigurationList;
357 | buildConfigurations = (
358 | F20732442BF5ECD5002F3A39 /* Debug */,
359 | F20732452BF5ECD5002F3A39 /* Release */,
360 | );
361 | defaultConfigurationIsVisible = 0;
362 | defaultConfigurationName = Release;
363 | };
364 | F20732462BF5ECD5002F3A39 /* Build configuration list for PBXNativeTarget "ContextCoreMLDemo" */ = {
365 | isa = XCConfigurationList;
366 | buildConfigurations = (
367 | F20732472BF5ECD5002F3A39 /* Debug */,
368 | F20732482BF5ECD5002F3A39 /* Release */,
369 | );
370 | defaultConfigurationIsVisible = 0;
371 | defaultConfigurationName = Release;
372 | };
373 | /* End XCConfigurationList section */
374 | };
375 | rootObject = F207322A2BF5ECD3002F3A39 /* Project object */;
376 | }
377 |
--------------------------------------------------------------------------------