From 4d633491417875f10f6007948ecaa3218e25c7a9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 2 Sep 2016 15:11:47 +0700 Subject: [PATCH 01/13] in progress --- ApiAI/Private/AIQueryRequest+Private.h | 2 + ApiAI/Private/AIQueryRequest+Private.m | 29 ++++- ApiAI/VoiceRequest/Classes/AIVoiceRequest.m | 113 ++++++++++-------- ApiAIDemo/ApiAI/AppDelegate.m | 3 +- .../SimpleVoiceRequestViewController.m | 2 + ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj | 60 +++++++++- ApiAIDemo/Podfile | 2 +- 7 files changed, 150 insertions(+), 61 deletions(-) diff --git a/ApiAI/Private/AIQueryRequest+Private.h b/ApiAI/Private/AIQueryRequest+Private.h index 16e4b06..1195b42 100644 --- a/ApiAI/Private/AIQueryRequest+Private.h +++ b/ApiAI/Private/AIQueryRequest+Private.h @@ -13,6 +13,8 @@ - (NSDictionary *)defaultHeaders; - (NSDictionary *)requestBodyDictionary; +- (NSDictionary *)getQueryParameters; + - (NSMutableURLRequest *)prepareDefaultRequest; - (NSArray *)contextsRequestPresentation; diff --git a/ApiAI/Private/AIQueryRequest+Private.m b/ApiAI/Private/AIQueryRequest+Private.m index 36bcc1a..02848ff 100644 --- a/ApiAI/Private/AIQueryRequest+Private.m +++ b/ApiAI/Private/AIQueryRequest+Private.m @@ -12,6 +12,10 @@ #import "AIRequestEntity_Private.h" #import "AINullabilityDefines.h" +static NSString *URLEncode(NSString *string) { + return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; +} + @implementation AIQueryRequest (Private) - (NSDictionary *)defaultHeaders @@ -64,6 +68,26 @@ - (NSDictionary *)requestBodyDictionary return [parameters copy]; } +- (NSDictionary *)getQueryParameters { + NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; + + if (self.version) { + parameters[@"version"] = self.version; + } + + return [parameters copy]; +} + +- (NSString *)queryFromQueryParameters:(NSDictionary *)queryParameters { + NSMutableArray *pairs = [NSMutableArray arrayWithCapacity:queryParameters.count]; + + [queryParameters enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + [pairs addObject:[NSString stringWithFormat:@"%@=%@", URLEncode(key), URLEncode(obj)]]; + }]; + + return [pairs componentsJoinedByString:@"&"]; +} + - (NSMutableURLRequest *)prepareDefaultRequest { id configuration = self.dataService.configuration; @@ -72,9 +96,8 @@ - (NSMutableURLRequest *)prepareDefaultRequest NSString *path = @"query"; - if (version) { - path = [path stringByAppendingFormat:@"?v=%@", version]; - } + NSString *getQueryString = [self queryFromQueryParameters: [self getQueryParameters]]; + path = [path stringByAppendingFormat:@"?%@", getQueryString]; NSURL *URL = [configuration.baseURL URLByAppendingPathComponent:path]; diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m index 776773e..65d175f 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m @@ -35,7 +35,7 @@ @class AIRecordDetector; -@interface AIVoiceRequest () +@interface AIVoiceRequest () @property(nonatomic, strong) NSOutputStream *output; @property(nonatomic, strong) NSInputStream *input; @@ -43,6 +43,8 @@ @interface AIVoiceRequest () @property(nonatomic, strong) AIStreamBuffer *streamBuffer; @property(nonatomic, copy) NSString *boundary; +@property(nonnull, strong) NSURLSession *session; + - (void)callSuperStart; @end @@ -60,6 +62,13 @@ @implementation AIVoiceRequest { SystemSoundID soundID; } +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler +{ + NSLog(@""); +} + - (instancetype)initWithDataService:(AIDataService *)dataService { self = [super initWithDataService:dataService]; @@ -68,11 +77,18 @@ - (instancetype)initWithDataService:(AIDataService *)dataService _recordDetector.delegate = self; self.useVADForAutoCommit = YES; -// [self prepare]; } return self; } +- (NSDictionary *)getQueryParameters { + NSMutableDictionary *parameters = [[super getQueryParameters] mutableCopy]; + + parameters[@"endofspeech"] = @"true"; + + return [parameters copy]; +} + - (void)prepare { self.boundary = [self creteBoundary]; @@ -88,43 +104,54 @@ - (void)prepare { [request setHTTPBodyStream:input]; - NSURLSession *session = self.dataService.URLSession; +// NSURLSession *session = self.dataService.URLSession; + NSURLSession *session = + [NSURLSession + sessionWithConfiguration:self.dataService.URLSession.configuration + delegate:self + delegateQueue:nil + ]; + + self.session = session; __weak typeof(self) selfWeak = self; - NSURLSessionDataTask *dataTask = - [session dataTaskWithRequest:request - completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { - if (!error) { - NSHTTPURLResponse *response = (NSHTTPURLResponse *)response1; - if ([self.dataService.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { - NSError *responseSerializeError = nil; - id responseData = - [NSJSONSerialization JSONObjectWithData:data - options:0 - error:&responseSerializeError]; - - if (!responseSerializeError) { - [self handleResponse:responseData]; - } else { - [self handleError:responseSerializeError]; - } - - } else { - NSError *responseStatusCodeError = - [NSError errorWithDomain:AIErrorDomain - code:NSURLErrorBadServerResponse - userInfo:@{ - NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode] - }]; - [selfWeak handleError:responseStatusCodeError]; - } - } else { - [selfWeak handleError:error]; - } - }]; - - self.dataTask = dataTask; + NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request]; + [dataTask resume]; + +// NSURLSessionDataTask *dataTask = +// [session dataTaskWithRequest:request +// completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { +// if (!error) { +// NSHTTPURLResponse *response = (NSHTTPURLResponse *)response1; +// if ([self.dataService.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { +// NSError *responseSerializeError = nil; +// id responseData = +// [NSJSONSerialization JSONObjectWithData:data +// options:0 +// error:&responseSerializeError]; +// +// if (!responseSerializeError) { +// [self handleResponse:responseData]; +// } else { +// [self handleError:responseSerializeError]; +// } +// +// } else { +// NSError *responseStatusCodeError = +// [NSError errorWithDomain:AIErrorDomain +// code:NSURLErrorBadServerResponse +// userInfo:@{ +// NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode] +// }]; +// [selfWeak handleError:responseStatusCodeError]; +// } +// } else { +// [selfWeak handleError:error]; +// } +// }]; +// +// self.dataTask = dataTask; self.streamBuffer = [[AIStreamBuffer alloc] initWithOutputStream:output]; @@ -136,31 +163,17 @@ - (void)start NSString *audioFileName = @"beep"; NSURL *audioFileURL = [[NSBundle bundleForClass:[self class]] URLForResource:audioFileName withExtension:@"caf"]; - NSLog(@"Bundle path: %@", [NSBundle bundleForClass:[self class]].bundlePath); - NSLog(@"Playing file: %@", audioFileURL); - if (audioFileURL) { soundID = 0; OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(audioFileURL), &soundID); if (status == noErr) { - -// if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_9_0) { -// __weak typeof(self) selfWeak = self; -// AudioServicesPlaySystemSoundWithCompletion(soundID, ^{ -// [selfWeak callSuperStart]; -// -// AudioServicesDisposeSystemSoundID(soundID); -// }); -// } else { -// OSStatus s = AudioServicesAddSystemSoundCompletion(soundID, CFRunLoopGetMain(), kCFRunLoopDefaultMode, MyAudioServicesSystemSoundCompletionProc, (__bridge void * _Nullable)(self)); AudioServicesPlaySystemSound(soundID); -// } } else { [self callSuperStart]; } diff --git a/ApiAIDemo/ApiAI/AppDelegate.m b/ApiAIDemo/ApiAI/AppDelegate.m index 3c879d2..4d8b78c 100644 --- a/ApiAIDemo/ApiAI/AppDelegate.m +++ b/ApiAIDemo/ApiAI/AppDelegate.m @@ -43,7 +43,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( id configuration = [[AIDefaultConfiguration alloc] init]; - configuration.clientAccessToken = @"YOUR_CLIENT_ACCESS_TOKEN"; +// configuration.clientAccessToken = @"YOUR_CLIENT_ACCESS_TOKEN"; + configuration.clientAccessToken = @"09604c7f91ce4cd8a4ede55eb5340b9d"; apiai.configuration = configuration; diff --git a/ApiAIDemo/ApiAI/SimpleVoiceRequestController/SimpleVoiceRequestViewController.m b/ApiAIDemo/ApiAI/SimpleVoiceRequestController/SimpleVoiceRequestViewController.m index 802a22b..573ad0b 100644 --- a/ApiAIDemo/ApiAI/SimpleVoiceRequestController/SimpleVoiceRequestViewController.m +++ b/ApiAIDemo/ApiAI/SimpleVoiceRequestController/SimpleVoiceRequestViewController.m @@ -46,6 +46,8 @@ - (IBAction)startListening:(id)sender AIVoiceRequest *request = [apiai voiceRequest]; + request.useVADForAutoCommit = _useVAD.isOn; + __weak typeof(self) selfWeak = self; [request setCompletionBlockSuccess:^(AIRequest *request, id response) { diff --git a/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj b/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj index 5a15f96..22c1489 100644 --- a/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj +++ b/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj @@ -238,12 +238,15 @@ isa = PBXNativeTarget; buildConfigurationList = 5891E0161941E9220043140B /* Build configuration list for PBXNativeTarget "ApiAIDemo" */; buildPhases = ( - C56E6EE44C68444733D450D2 /* 📦 Check Pods Manifest.lock */, + C1B5FC3FFDEE72FFA5D59F26 /* 📦 Check Pods Manifest.lock */, + C56E6EE44C68444733D450D2 /* [CP] Check Pods Manifest.lock */, 5891DFE01941E9210043140B /* Sources */, 5891DFE11941E9210043140B /* Frameworks */, 5891DFE21941E9210043140B /* Resources */, - 0EC5C4B5A9AB66030A95E7E5 /* 📦 Embed Pods Frameworks */, - 2BA6AED7FE19D98244D3652C /* 📦 Copy Pods Resources */, + 0EC5C4B5A9AB66030A95E7E5 /* [CP] Embed Pods Frameworks */, + 2BA6AED7FE19D98244D3652C /* [CP] Copy Pods Resources */, + 6B8A8F44E67AA24389E364CE /* 📦 Embed Pods Frameworks */, + 859228A2E7DDF213D2DD26DF /* 📦 Copy Pods Resources */, ); buildRules = ( ); @@ -298,7 +301,37 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 0EC5C4B5A9AB66030A95E7E5 /* 📦 Embed Pods Frameworks */ = { + 0EC5C4B5A9AB66030A95E7E5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemo/Pods-ApiAIDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 2BA6AED7FE19D98244D3652C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemo/Pods-ApiAIDemo-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 6B8A8F44E67AA24389E364CE /* 📦 Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -313,7 +346,7 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemo/Pods-ApiAIDemo-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 2BA6AED7FE19D98244D3652C /* 📦 Copy Pods Resources */ = { + 859228A2E7DDF213D2DD26DF /* 📦 Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -328,7 +361,7 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemo/Pods-ApiAIDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - C56E6EE44C68444733D450D2 /* 📦 Check Pods Manifest.lock */ = { + C1B5FC3FFDEE72FFA5D59F26 /* 📦 Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -343,6 +376,21 @@ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; + C56E6EE44C68444733D450D2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ApiAIDemo/Podfile b/ApiAIDemo/Podfile index e5de4c3..6cdfc3f 100644 --- a/ApiAIDemo/Podfile +++ b/ApiAIDemo/Podfile @@ -7,7 +7,7 @@ source 'https://github.com/CocoaPods/Specs.git' target "ApiAIDemo" do -pod 'ApiAI' #, :path => '../' +pod 'ApiAI' , :path => '../' pod 'MBProgressHUD' end From 6024ce8b34520b3720f26e77867123b0bb389310 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 30 Sep 2016 11:26:01 +0700 Subject: [PATCH 02/13] implemented support end of speech --- ApiAI/Private/AIQueryRequest+Private.m | 9 +- ApiAI/Private/Streamer/AIStreamBuffer.m | 4 + ApiAI/VoiceRequest/Classes/AIVoiceRequest.m | 118 ++++++++++++-------- ApiAIDemo/ApiAI/AppDelegate.m | 6 +- 4 files changed, 87 insertions(+), 50 deletions(-) diff --git a/ApiAI/Private/AIQueryRequest+Private.m b/ApiAI/Private/AIQueryRequest+Private.m index 02848ff..c9cd6ba 100644 --- a/ApiAI/Private/AIQueryRequest+Private.m +++ b/ApiAI/Private/AIQueryRequest+Private.m @@ -72,7 +72,7 @@ - (NSDictionary *)getQueryParameters { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; if (self.version) { - parameters[@"version"] = self.version; + parameters[@"v"] = self.version; } return [parameters copy]; @@ -97,10 +97,15 @@ - (NSMutableURLRequest *)prepareDefaultRequest NSString *path = @"query"; NSString *getQueryString = [self queryFromQueryParameters: [self getQueryParameters]]; - path = [path stringByAppendingFormat:@"?%@", getQueryString]; +// path = [path stringByAppendingFormat:@"?%@", getQueryString]; NSURL *URL = [configuration.baseURL URLByAppendingPathComponent:path]; + NSURLComponents *components = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO]; + components.query = getQueryString; + + URL = components.URL; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL]; [request setHTTPMethod:@"POST"]; diff --git a/ApiAI/Private/Streamer/AIStreamBuffer.m b/ApiAI/Private/Streamer/AIStreamBuffer.m index 9ef34c1..55ecd84 100644 --- a/ApiAI/Private/Streamer/AIStreamBuffer.m +++ b/ApiAI/Private/Streamer/AIStreamBuffer.m @@ -140,6 +140,10 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode break; } + case NSStreamEventEndEncountered: { + NSLog(@""); + break; + } default: break; } diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m index 65d175f..720139a 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m @@ -35,7 +35,7 @@ @class AIRecordDetector; -@interface AIVoiceRequest () +@interface AIVoiceRequest () @property(nonatomic, strong) NSOutputStream *output; @property(nonatomic, strong) NSInputStream *input; @@ -62,9 +62,41 @@ @implementation AIVoiceRequest { SystemSoundID soundID; } +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend +{ + NSLog(@""); +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task +didCompleteWithError:(nullable NSError *)error +{ + NSLog(@""); +} + - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler +{ + completionHandler(NSURLSessionResponseAllow); +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask +{ + NSLog(@""); +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask +didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask +{ + NSLog(@""); +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { NSLog(@""); } @@ -94,6 +126,10 @@ - (void)prepare { NSMutableURLRequest *request = self.prepareDefaultRequest; + [request addValue:@"100-continue" forHTTPHeaderField:@"Expect"]; + + request.HTTPShouldUsePipelining = YES; + NSInputStream *input = nil; NSOutputStream *output = nil; @@ -104,55 +140,43 @@ - (void)prepare { [request setHTTPBodyStream:input]; -// NSURLSession *session = self.dataService.URLSession; - NSURLSession *session = - [NSURLSession - sessionWithConfiguration:self.dataService.URLSession.configuration - delegate:self - delegateQueue:nil - ]; - - self.session = session; + NSURLSession *session = self.dataService.URLSession; __weak typeof(self) selfWeak = self; - NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request]; - [dataTask resume]; - -// NSURLSessionDataTask *dataTask = -// [session dataTaskWithRequest:request -// completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { -// if (!error) { -// NSHTTPURLResponse *response = (NSHTTPURLResponse *)response1; -// if ([self.dataService.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { -// NSError *responseSerializeError = nil; -// id responseData = -// [NSJSONSerialization JSONObjectWithData:data -// options:0 -// error:&responseSerializeError]; -// -// if (!responseSerializeError) { -// [self handleResponse:responseData]; -// } else { -// [self handleError:responseSerializeError]; -// } -// -// } else { -// NSError *responseStatusCodeError = -// [NSError errorWithDomain:AIErrorDomain -// code:NSURLErrorBadServerResponse -// userInfo:@{ -// NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode] -// }]; -// [selfWeak handleError:responseStatusCodeError]; -// } -// } else { -// [selfWeak handleError:error]; -// } -// }]; -// -// self.dataTask = dataTask; - + NSURLSessionDataTask *dataTask = + [session dataTaskWithRequest:request + completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { + if (!error) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)response1; + if ([self.dataService.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { + NSError *responseSerializeError = nil; + id responseData = + [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&responseSerializeError]; + + if (!responseSerializeError) { + [self handleResponse:responseData]; + } else { + [self handleError:responseSerializeError]; + } + + } else { + NSError *responseStatusCodeError = + [NSError errorWithDomain:AIErrorDomain + code:NSURLErrorBadServerResponse + userInfo:@{ + NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode] + }]; + [selfWeak handleError:responseStatusCodeError]; + } + } else { + [selfWeak handleError:error]; + } + }]; + + self.dataTask = dataTask; self.streamBuffer = [[AIStreamBuffer alloc] initWithOutputStream:output]; [_streamBuffer open]; diff --git a/ApiAIDemo/ApiAI/AppDelegate.m b/ApiAIDemo/ApiAI/AppDelegate.m index 4d8b78c..eee39c0 100644 --- a/ApiAIDemo/ApiAI/AppDelegate.m +++ b/ApiAIDemo/ApiAI/AppDelegate.m @@ -44,7 +44,11 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( id configuration = [[AIDefaultConfiguration alloc] init]; // configuration.clientAccessToken = @"YOUR_CLIENT_ACCESS_TOKEN"; - configuration.clientAccessToken = @"09604c7f91ce4cd8a4ede55eb5340b9d"; + configuration.clientAccessToken = @"95a1bad594414951b1f42dfae31d8176"; + configuration.baseURL = [NSURL URLWithString:@"http://openapi-dev/api/"]; + +// configuration.clientAccessToken = @"0cc6d0ded92d49968dad4ddcb083b48f"; +// configuration.baseURL = [NSURL URLWithString:@"http://192.168.1.12:8080/api/"]; apiai.configuration = configuration; From d07d949c552f519adada0aac2fad0b5944fe8dab Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 12:55:47 +0700 Subject: [PATCH 03/13] Add support events. Deprecated voice recignitions API. --- ApiAI.podspec.json | 4 +- ApiAI.xcodeproj/project.pbxproj | 24 ++++ ApiAI/Classes/AINullabilityDefines.h | 2 + ApiAI/Classes/ApiAI.h | 30 +++- ApiAI/EventRequest/AIEvent.h | 19 +++ ApiAI/EventRequest/AIEvent.m | 32 +++++ ApiAI/EventRequest/AIEventRequest.h | 16 +++ ApiAI/EventRequest/AIEventRequest.m | 136 ++++++++++++++++++ ApiAI/Private/Streamer/AIStreamBuffer.m | 3 + .../Classes/AIVoiceFileRequest.h | 12 +- ApiAI/VoiceRequest/Classes/AIVoiceRequest.h | 21 ++- ApiAI/VoiceRequest/Classes/AIVoiceRequest.m | 105 ++++++-------- ApiAIDemo/ApiAI/AppDelegate.m | 7 +- ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj | 8 +- .../xcshareddata/xcschemes/ApiAIDemo.xcscheme | 7 + 15 files changed, 339 insertions(+), 87 deletions(-) create mode 100644 ApiAI/EventRequest/AIEvent.h create mode 100644 ApiAI/EventRequest/AIEvent.m create mode 100644 ApiAI/EventRequest/AIEventRequest.h create mode 100644 ApiAI/EventRequest/AIEventRequest.m diff --git a/ApiAI.podspec.json b/ApiAI.podspec.json index 2704e4f..87b639a 100644 --- a/ApiAI.podspec.json +++ b/ApiAI.podspec.json @@ -1,6 +1,6 @@ { "name": "ApiAI", - "version": "0.5.5", + "version": "0.6.0", "license": "Apache 2.0", "summary": "The API.AI iOS SDK makes it easy to integrate speech recognition with API.AI natural language processing API on iOS devices.", "homepage": "http://api.ai/", @@ -10,7 +10,7 @@ "source": { "git": "https://github.com/api-ai/api-ai-ios-sdk.git", - "tag": "v0.5.5" + "tag": "v0.6.0" }, "requires_arc": true, diff --git a/ApiAI.xcodeproj/project.pbxproj b/ApiAI.xcodeproj/project.pbxproj index 5e39220..54d020e 100644 --- a/ApiAI.xcodeproj/project.pbxproj +++ b/ApiAI.xcodeproj/project.pbxproj @@ -151,6 +151,10 @@ 585BC6C91A15F9E800B2584A /* AIDefaultConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 585BC6C81A15F9E800B2584A /* AIDefaultConfiguration.m */; }; 5862C2D61BAEABE1007C6C4F /* AIRequestContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 5862C2D51BAEABE1007C6C4F /* AIRequestContext.m */; }; 5862E2FE1B6A103B00F6F712 /* AIVoiceFileRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5862E2FD1B6A103B00F6F712 /* AIVoiceFileRequest.m */; }; + 5865DD1C1DFA7CA50073D1A3 /* AIEventRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */; }; + 5865DD1F1DFA7CD00073D1A3 /* AIEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */; }; + 5865DD201DFA7E4A0073D1A3 /* AIEventRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */; }; + 5865DD211DFA7E4A0073D1A3 /* AIEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */; }; 5867737D1BD0F76000E1253D /* speech_d.wav in Resources */ = {isa = PBXBuildFile; fileRef = 5867737C1BD0F76000E1253D /* speech_d.wav */; }; 5869BCFD1B37E56A000B99B7 /* AINullabilityDefines.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 5869BCFC1B37E505000B99B7 /* AINullabilityDefines.h */; }; 587074061CA184C900C4535B /* AIVoiceRequestButton.xib in Resources */ = {isa = PBXBuildFile; fileRef = 581AB39E1A245D8300E8A190 /* AIVoiceRequestButton.xib */; }; @@ -307,6 +311,10 @@ 5862E2FB1B6A103300F6F712 /* AIVoiceFileRequest_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIVoiceFileRequest_Private.h; sourceTree = ""; }; 5862E2FC1B6A103B00F6F712 /* AIVoiceFileRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIVoiceFileRequest.h; sourceTree = ""; }; 5862E2FD1B6A103B00F6F712 /* AIVoiceFileRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIVoiceFileRequest.m; sourceTree = ""; }; + 5865DD1A1DFA7CA50073D1A3 /* AIEventRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIEventRequest.h; sourceTree = ""; }; + 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIEventRequest.m; sourceTree = ""; }; + 5865DD1D1DFA7CD00073D1A3 /* AIEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIEvent.h; sourceTree = ""; }; + 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIEvent.m; sourceTree = ""; }; 5867737C1BD0F76000E1253D /* speech_d.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = speech_d.wav; sourceTree = ""; }; 5869BCFC1B37E505000B99B7 /* AINullabilityDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AINullabilityDefines.h; sourceTree = ""; }; 588D23831AFB3C95008289F1 /* AIResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIResponse.h; sourceTree = ""; }; @@ -515,6 +523,17 @@ path = Private; sourceTree = ""; }; + 5865DD191DFA7C890073D1A3 /* EventRequest */ = { + isa = PBXGroup; + children = ( + 5865DD1A1DFA7CA50073D1A3 /* AIEventRequest.h */, + 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */, + 5865DD1D1DFA7CD00073D1A3 /* AIEvent.h */, + 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */, + ); + path = EventRequest; + sourceTree = ""; + }; 588D23811AFB3C95008289F1 /* Response */ = { isa = PBXGroup; children = ( @@ -626,6 +645,7 @@ 58C2A83019BEE0E000632C2F /* ApiAI */ = { isa = PBXGroup; children = ( + 5865DD191DFA7C890073D1A3 /* EventRequest */, 58FF3A1F1C43BB210038BD9D /* UserEntities */, 58D697561B67AC3E00693710 /* VoiceFileRequest */, 58D696E01B679D0300693710 /* VoiceRequest */, @@ -1137,6 +1157,7 @@ 580C6A7A1CA17F8E00C55313 /* AISessionIdentifierStorage.m in Sources */, 580C6A6F1CA17F8100C55313 /* AIRequestEntry.m in Sources */, 580C6A771CA17F8E00C55313 /* AIDataService.m in Sources */, + 5865DD201DFA7E4A0073D1A3 /* AIEventRequest.m in Sources */, 580C6A6E1CA17F8100C55313 /* AIResponseConstants.m in Sources */, 580C6A781CA17F8E00C55313 /* AIStreamBuffer.m in Sources */, 580C6A731CA17F8100C55313 /* AIDefaultConfiguration.m in Sources */, @@ -1144,6 +1165,7 @@ 580C6A761CA17F8100C55313 /* AIQueryRequest.m in Sources */, 580C6A721CA17F8100C55313 /* AITextRequest.m in Sources */, 580C6A741CA17F8100C55313 /* AIRequestEntity.m in Sources */, + 5865DD211DFA7E4A0073D1A3 /* AIEvent.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1183,6 +1205,7 @@ 58C2A85B19BEE0E000632C2F /* ApiAI.m in Sources */, 588D239E1AFB3C95008289F1 /* AIResponseParameter.m in Sources */, 581AB3AF1A245D8300E8A190 /* AIVoiceRequestButton.m in Sources */, + 5865DD1C1DFA7CA50073D1A3 /* AIEventRequest.m in Sources */, 58D697041B679D0300693710 /* AIAudioUtils.c in Sources */, 58D697071B679D0300693710 /* AISoundRecorderConstants.m in Sources */, 581AB3B01A245D8300E8A190 /* AIEllipseView.m in Sources */, @@ -1190,6 +1213,7 @@ 58D6975E1B67ACD300693710 /* AIQueryRequest+Private.m in Sources */, 588D23AE1AFB3E26008289F1 /* AIRequest+AIMappedResponse.m in Sources */, 58C2A85D19BEE0E000632C2F /* AITextRequest.m in Sources */, + 5865DD1F1DFA7CD00073D1A3 /* AIEvent.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ApiAI/Classes/AINullabilityDefines.h b/ApiAI/Classes/AINullabilityDefines.h index 36fd040..bfdff81 100644 --- a/ApiAI/Classes/AINullabilityDefines.h +++ b/ApiAI/Classes/AINullabilityDefines.h @@ -63,5 +63,7 @@ #endif +#define AI_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#define AI_DEPRECATED_MSG_ATTRIBUTE(msg) __attribute((deprecated((msg)))) #endif diff --git a/ApiAI/Classes/ApiAI.h b/ApiAI/Classes/ApiAI.h index 16d53b0..cf9a566 100644 --- a/ApiAI/Classes/ApiAI.h +++ b/ApiAI/Classes/ApiAI.h @@ -66,7 +66,7 @@ typedef NS_ENUM(NSUInteger, AIRequestType) { /*! Simple text request type */ AIRequestTypeText, /*! Voice request type with VAD(Voice activity detection) for detect end of phrase. */ - AIRequestTypeVoice = 1 + AIRequestTypeVoice DEPRECATED_MSG_ATTRIBUTE("Use :voiceRequest or :textRequest methods") = 1 }; /*! @@ -138,7 +138,16 @@ typedef NS_ENUM(NSUInteger, AIRequestType) { - (AIRequest *)requestWithType:(AIRequestType)requestType DEPRECATED_MSG_ATTRIBUTE("Use :voiceRequest or :textRequest methods"); #if AI_SUPPORT_VOICE_REQUEST -- (AIVoiceRequest *)voiceRequest; +/*! + API.AI speech recognition is going to be deprecated soon. + Use Google Cloud Speech API or other solutions. + + This is request type available only for old paid plans. + It doesn't working for new users. + + Will be removed on 1 Feb 2016. + */ +- (AIVoiceRequest *)voiceRequest AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016."); #endif #if __has_include("AITextRequest.h") @@ -151,9 +160,18 @@ typedef NS_ENUM(NSUInteger, AIRequestType) { #if __has_include("AIVoiceFileRequest.h") -- (AIVoiceFileRequest *)voiceFileRequestWithFileURL:(NSURL *)fileURL; -- (AIVoiceFileRequest *)voiceFileRequestWithStream:(NSInputStream *)inputStream; -- (AIVoiceFileRequest *)voiceFileRequestWithData:(NSData *)fileData; +/*! + API.AI speech recognition is going to be deprecated soon. + Use Google Cloud Speech API or other solutions. + + This is request type available only for old paid plans. + It doesn't working for new users. + + Will be removed on 1 Feb 2016. + */ +- (AIVoiceFileRequest *)voiceFileRequestWithFileURL:(NSURL *)fileURL AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016."); +- (AIVoiceFileRequest *)voiceFileRequestWithStream:(NSInputStream *)inputStream AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016."); +- (AIVoiceFileRequest *)voiceFileRequestWithData:(NSData *)fileData AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016."); #endif /*! @@ -175,4 +193,4 @@ typedef NS_ENUM(NSUInteger, AIRequestType) { - (void)cancellAllRequests; -@end \ No newline at end of file +@end diff --git a/ApiAI/EventRequest/AIEvent.h b/ApiAI/EventRequest/AIEvent.h new file mode 100644 index 0000000..88ccf3c --- /dev/null +++ b/ApiAI/EventRequest/AIEvent.h @@ -0,0 +1,19 @@ +// +// AIEvent.h +// ApiAI +// +// Created by Kuragin Dmitriy on 09/12/2016. +// Copyright © 2016 Kuragin Dmitriy. All rights reserved. +// + +#import + +@interface AIEvent : NSObject + +@property(nonatomic, copy) NSString *event; +@property(nonatomic, copy) NSDictionary *data; + +- (instancetype)initWithEvent:(NSString *)event andData:(NSDictionary *)data; +- (instancetype)initWithEvent:(NSString *)event; + +@end diff --git a/ApiAI/EventRequest/AIEvent.m b/ApiAI/EventRequest/AIEvent.m new file mode 100644 index 0000000..b33d924 --- /dev/null +++ b/ApiAI/EventRequest/AIEvent.m @@ -0,0 +1,32 @@ +// +// AIEvent.m +// ApiAI +// +// Created by Kuragin Dmitriy on 09/12/2016. +// Copyright © 2016 Kuragin Dmitriy. All rights reserved. +// + +#import "AIEvent.h" + +@implementation AIEvent + +- (instancetype)initWithEvent:(NSString *)event andData:(NSDictionary *)data { + self = [super init]; + if (self) { + self.event = event; + self.data = data; + } + + return self; +} + +- (instancetype)initWithEvent:(NSString *)event { + self = [super init]; + if (self) { + self.event = event; + self.data = nil; + } + return self; +} + +@end diff --git a/ApiAI/EventRequest/AIEventRequest.h b/ApiAI/EventRequest/AIEventRequest.h new file mode 100644 index 0000000..6811c2a --- /dev/null +++ b/ApiAI/EventRequest/AIEventRequest.h @@ -0,0 +1,16 @@ +// +// AIEventRequest.h +// ApiAI +// +// Created by Kuragin Dmitriy on 09/12/2016. +// Copyright © 2016 Kuragin Dmitriy. All rights reserved. +// + +#import "AIQueryRequest.h" +#import "AIEvent.h" + +@interface AIEventRequest : AIQueryRequest + +@property(nonatomic, strong) AIEvent *event; + +@end diff --git a/ApiAI/EventRequest/AIEventRequest.m b/ApiAI/EventRequest/AIEventRequest.m new file mode 100644 index 0000000..9131749 --- /dev/null +++ b/ApiAI/EventRequest/AIEventRequest.m @@ -0,0 +1,136 @@ +// +// AIEventRequest.m +// ApiAI +// +// Created by Kuragin Dmitriy on 09/12/2016. +// Copyright © 2016 Kuragin Dmitriy. All rights reserved. +// + +#import "AIEventRequest.h" +#import "AIDataService.h" +#import "AIDataService_Private.h" +#import "AIConfiguration.h" +#import "AIRequestEntity_Private.h" +#import "AIQueryRequest+Private.h" +#import "AIRequest_Private.h" + +#import "AIResponseConstants.h" + +@implementation AIEventRequest + +- (void)configureHTTPRequest { + AIDataService *dataService = self.dataService; + id configuration = dataService.configuration; + + NSString *version = self.version; + + NSString *path = @"query"; + + if (version) { + path = [path stringByAppendingFormat:@"?v=%@", version]; + } + + NSString *timeZoneString = self.timeZone ? self.timeZone.name : [NSTimeZone localTimeZone].name; + + NSDictionary *eventDictionary = @{ + @"event": _event.event, + @"data": _event.data + }; + + NSMutableDictionary *parameters = [@{ + @"event": eventDictionary, + @"timezone": timeZoneString, + @"lang": self.lang + } mutableCopy]; + + if (self.resetContexts) { + parameters[@"resetContexts"] = @(YES); + } + + if ([self.requestContexts count]) { + parameters[@"contexts"] = [self contextsRequestPresentation]; + } + + if ([self.entities count]) { + NSMutableArray *entities = [NSMutableArray array]; + [self.entities enumerateObjectsUsingBlock:^(AIRequestEntity *obj, NSUInteger idx, BOOL *stop) { + [entities addObject:obj.dictionaryPresentation]; + }]; + + parameters[@"entities"] = [entities copy]; + } + + parameters[@"sessionId"] = self.sessionId; + + AIQueryRequestLocation *location = self.location; + + if (location) { + parameters[@"location"] = @{ + @"latitude": @(location.latitude), + @"longitude": @(location.longitude) + }; + } + + NSURL *URL = [configuration.baseURL URLByAppendingPathComponent:path]; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL]; + + [request setHTTPMethod:@"POST"]; + + NSError *serializeError = nil; + + NSData *requestData = + [NSJSONSerialization dataWithJSONObject:parameters + options:0 + error:&serializeError]; + + [request setHTTPBody:requestData]; + + [request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; + + [request setValue:[NSString stringWithFormat:@"Bearer %@", configuration.clientAccessToken] + forHTTPHeaderField:@"Authorization"]; + + NSURLSession *session = dataService.URLSession; + + __weak typeof(self) selfWeak = self; + + NSURLSessionDataTask *dataTask = + [session dataTaskWithRequest:request + completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { + if (!error) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)response1; + if ([dataService.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { + NSError *responseSerializeError = nil; + id responseData = + [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&responseSerializeError]; + + if (!responseSerializeError) { + [self handleResponse:responseData]; + } else { + [self handleError:responseSerializeError]; + } + + } else { + NSError *responseStatusCodeError = + [NSError errorWithDomain:AIErrorDomain + code:NSURLErrorBadServerResponse + userInfo:@{ + NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode] + }]; + [selfWeak handleError:responseStatusCodeError]; + } + } else { + [selfWeak handleError:error]; + } + }]; + + self.dataTask = dataTask; + + [dataTask resume]; + +} + +@end diff --git a/ApiAI/Private/Streamer/AIStreamBuffer.m b/ApiAI/Private/Streamer/AIStreamBuffer.m index 55ecd84..1bc1336 100644 --- a/ApiAI/Private/Streamer/AIStreamBuffer.m +++ b/ApiAI/Private/Streamer/AIStreamBuffer.m @@ -112,6 +112,9 @@ - (void)flush - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { + if (eventCode != NSStreamEventHasSpaceAvailable) { + NSLog(@""); + } switch (eventCode) { case NSStreamEventOpenCompleted: self.opened = YES; diff --git a/ApiAI/VoiceFileRequest/Classes/AIVoiceFileRequest.h b/ApiAI/VoiceFileRequest/Classes/AIVoiceFileRequest.h index 07966c3..73b31e5 100644 --- a/ApiAI/VoiceFileRequest/Classes/AIVoiceFileRequest.h +++ b/ApiAI/VoiceFileRequest/Classes/AIVoiceFileRequest.h @@ -8,8 +8,18 @@ #import "AIQueryRequest.h" +/*! + API.AI speech recognition is going to be deprecated soon. + Use Google Cloud Speech API or other solutions. + + This is request type available only for old paid plans. + It doesn't working for new users. + + Will be removed on 1 Feb 2016. + */ +AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016.") @interface AIVoiceFileRequest : AIQueryRequest -@property(nonatomic, copy) NSString *contentType; +@property(nonatomic, copy) NSString *contentType AI_DEPRECATED_ATTRIBUTE; @end diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.h b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.h index e24e4fb..d3ea0bb 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.h +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.h @@ -42,6 +42,16 @@ typedef void(^SoundRecordBeginBlock)(AIRequest *request); */ typedef void(^SoundRecordEndBlock)(AIRequest *request); +/*! + API.AI speech recognition is going to be deprecated soon. + Use Google Cloud Speech API or other solutions. + + This is request type available only for old paid plans. + It doesn't working for new users. + + Will be removed on 1 Feb 2016. + */ +AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016.") @interface AIVoiceRequest : AIQueryRequest /*! @@ -49,9 +59,8 @@ typedef void(^SoundRecordEndBlock)(AIRequest *request); @property soundLevelHandleBlock @discussion Sound level handler. Default is nil. - */ -@property(nonatomic, copy) SoundLevelHandleBlock soundLevelHandleBlock; +@property(nonatomic, copy) SoundLevelHandleBlock soundLevelHandleBlock AI_DEPRECATED_ATTRIBUTE; /*! @@ -60,7 +69,7 @@ typedef void(^SoundRecordEndBlock)(AIRequest *request); @discussion Record begin handler. Default is nil. */ -@property(nonatomic, copy) SoundRecordBeginBlock soundRecordBeginBlock; +@property(nonatomic, copy) SoundRecordBeginBlock soundRecordBeginBlock AI_DEPRECATED_ATTRIBUTE; /*! @@ -69,7 +78,7 @@ typedef void(^SoundRecordEndBlock)(AIRequest *request); @discussion Record end handler. Default is nil. */ -@property(nonatomic, copy) SoundRecordEndBlock soundRecordEndBlock; +@property(nonatomic, copy) SoundRecordEndBlock soundRecordEndBlock AI_DEPRECATED_ATTRIBUTE; /*! @@ -78,11 +87,11 @@ typedef void(^SoundRecordEndBlock)(AIRequest *request); @discussion Use Voice Activity Detection for detect end of speech. Default is YES. */ -@property(nonatomic, assign) BOOL useVADForAutoCommit; +@property(nonatomic, assign) BOOL useVADForAutoCommit AI_DEPRECATED_ATTRIBUTE; /*! * Manually stop listening and send request to server. */ -- (void)commitVoice; +- (void)commitVoice AI_DEPRECATED_ATTRIBUTE; @end diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m index 720139a..1f653ed 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m @@ -33,9 +33,14 @@ #import + + + + + @class AIRecordDetector; -@interface AIVoiceRequest () +@interface AIVoiceRequest () @property(nonatomic, strong) NSOutputStream *output; @property(nonatomic, strong) NSInputStream *input; @@ -62,45 +67,6 @@ @implementation AIVoiceRequest { SystemSoundID soundID; } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task - didSendBodyData:(int64_t)bytesSent - totalBytesSent:(int64_t)totalBytesSent -totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend -{ - NSLog(@""); -} - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task -didCompleteWithError:(nullable NSError *)error -{ - NSLog(@""); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask -didReceiveResponse:(NSURLResponse *)response - completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler -{ - completionHandler(NSURLSessionResponseAllow); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask -didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask -{ - NSLog(@""); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask -didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask -{ - NSLog(@""); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask - didReceiveData:(NSData *)data -{ - NSLog(@""); -} - - (instancetype)initWithDataService:(AIDataService *)dataService { self = [super initWithDataService:dataService]; @@ -127,6 +93,7 @@ - (void)prepare { NSMutableURLRequest *request = self.prepareDefaultRequest; [request addValue:@"100-continue" forHTTPHeaderField:@"Expect"]; +// [request addValue:@"close" forHTTPHeaderField:@"Connection"]; request.HTTPShouldUsePipelining = YES; @@ -140,10 +107,11 @@ - (void)prepare { [request setHTTPBodyStream:input]; + self.streamBuffer = [[AIStreamBuffer alloc] initWithOutputStream:output]; + NSURLSession *session = self.dataService.URLSession; __weak typeof(self) selfWeak = self; - NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * __AI_NULLABLE data, NSURLResponse * __AI_NULLABLE response1, NSError * __AI_NULLABLE error) { @@ -178,8 +146,11 @@ - (void)prepare { self.dataTask = dataTask; - self.streamBuffer = [[AIStreamBuffer alloc] initWithOutputStream:output]; [_streamBuffer open]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [_streamBuffer close]; + }); } - (void)start @@ -291,26 +262,36 @@ - (NSString *)creteBoundary + (void)createBoundInputStream:(NSInputStream **)inputStreamPtr outputStream:(NSOutputStream **)outputStreamPtr bufferSize:(NSUInteger)bufferSize { - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; - - assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ); - - readStream = NULL; - writeStream = NULL; - - CFStreamCreateBoundPair( - NULL, - ((inputStreamPtr != nil) ? &readStream : NULL), - ((outputStreamPtr != nil) ? &writeStream : NULL), - (CFIndex) bufferSize - ); - - if (inputStreamPtr != NULL) { - *inputStreamPtr = CFBridgingRelease(readStream); - } - if (outputStreamPtr != NULL) { - *outputStreamPtr = CFBridgingRelease(writeStream); + if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) { + NSInputStream *input = NULL; + NSOutputStream *output = NULL; + + [NSStream getBoundStreamsWithBufferSize:bufferSize inputStream:&input outputStream:&output]; + + *inputStreamPtr = input; + *outputStreamPtr = output; + } else { + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ); + + readStream = NULL; + writeStream = NULL; + + CFStreamCreateBoundPair( + NULL, + ((inputStreamPtr != nil) ? &readStream : NULL), + ((outputStreamPtr != nil) ? &writeStream : NULL), + (CFIndex) bufferSize + ); + + if (inputStreamPtr != NULL) { + *inputStreamPtr = CFBridgingRelease(readStream); + } + if (outputStreamPtr != NULL) { + *outputStreamPtr = CFBridgingRelease(writeStream); + } } } diff --git a/ApiAIDemo/ApiAI/AppDelegate.m b/ApiAIDemo/ApiAI/AppDelegate.m index eee39c0..e092415 100644 --- a/ApiAIDemo/ApiAI/AppDelegate.m +++ b/ApiAIDemo/ApiAI/AppDelegate.m @@ -43,12 +43,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( id configuration = [[AIDefaultConfiguration alloc] init]; -// configuration.clientAccessToken = @"YOUR_CLIENT_ACCESS_TOKEN"; - configuration.clientAccessToken = @"95a1bad594414951b1f42dfae31d8176"; - configuration.baseURL = [NSURL URLWithString:@"http://openapi-dev/api/"]; - -// configuration.clientAccessToken = @"0cc6d0ded92d49968dad4ddcb083b48f"; -// configuration.baseURL = [NSURL URLWithString:@"http://192.168.1.12:8080/api/"]; + configuration.clientAccessToken = @"YOUR_CLIENT_ACCESS_TOKEN"; apiai.configuration = configuration; diff --git a/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj b/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj index 22c1489..dbc2251 100644 --- a/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj +++ b/ApiAIDemo/ApiAIDemo.xcodeproj/project.pbxproj @@ -238,7 +238,7 @@ isa = PBXNativeTarget; buildConfigurationList = 5891E0161941E9220043140B /* Build configuration list for PBXNativeTarget "ApiAIDemo" */; buildPhases = ( - C1B5FC3FFDEE72FFA5D59F26 /* 📦 Check Pods Manifest.lock */, + C1B5FC3FFDEE72FFA5D59F26 /* [CP] Check Pods Manifest.lock */, C56E6EE44C68444733D450D2 /* [CP] Check Pods Manifest.lock */, 5891DFE01941E9210043140B /* Sources */, 5891DFE11941E9210043140B /* Frameworks */, @@ -361,19 +361,19 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemo/Pods-ApiAIDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - C1B5FC3FFDEE72FFA5D59F26 /* 📦 Check Pods Manifest.lock */ = { + C1B5FC3FFDEE72FFA5D59F26 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; C56E6EE44C68444733D450D2 /* [CP] Check Pods Manifest.lock */ = { diff --git a/ApiAIDemo/ApiAIDemo.xcodeproj/xcshareddata/xcschemes/ApiAIDemo.xcscheme b/ApiAIDemo/ApiAIDemo.xcodeproj/xcshareddata/xcschemes/ApiAIDemo.xcscheme index e6718e1..27eca60 100644 --- a/ApiAIDemo/ApiAIDemo.xcodeproj/xcshareddata/xcschemes/ApiAIDemo.xcscheme +++ b/ApiAIDemo/ApiAIDemo.xcodeproj/xcshareddata/xcschemes/ApiAIDemo.xcscheme @@ -61,6 +61,13 @@ ReferencedContainer = "container:ApiAIDemo.xcodeproj"> + + + + From 71e5847c693011fcd97209844aabebfe51a0caf0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 13:09:20 +0700 Subject: [PATCH 04/13] rich messages support. --- ApiAI.podspec.json | 25 ++++++++++++++++++- .../Response/Classes/AIResponseFulfillment.h | 8 +++++- .../Response/Classes/AIResponseFulfillment.m | 1 + ApiAI/VoiceRequest/Classes/AIVoiceRequest.m | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ApiAI.podspec.json b/ApiAI.podspec.json index 87b639a..122042f 100644 --- a/ApiAI.podspec.json +++ b/ApiAI.podspec.json @@ -220,9 +220,32 @@ "requires_arc": true, + "dependencies": { + "ApiAI/Core": [] + } + }, + { + "name": "Events", + + "source_files": [ + "ApiAI/EventRequest/**/*.{h,m,c}", + ], + + "resources": [], + + "public_header_files": [ + "ApiAI/EventRequest/**/*.{h}" + ], + + "ios": { + "frameworks": ["Foundation"] + }, + + "requires_arc": true, + "dependencies": { "ApiAI/Core": [] } } ] -} \ No newline at end of file +} diff --git a/ApiAI/Response/Classes/AIResponseFulfillment.h b/ApiAI/Response/Classes/AIResponseFulfillment.h index 9feaea4..e7c625f 100644 --- a/ApiAI/Response/Classes/AIResponseFulfillment.h +++ b/ApiAI/Response/Classes/AIResponseFulfillment.h @@ -20,6 +20,7 @@ ***********************************************************************************************************************/ #import +#import "AINullabilityDefines.h" /** Fulfillment @@ -32,6 +33,11 @@ /** Response speech. */ -@property(nonatomic, copy, readonly) NSString *speech; +@property(nonatomic, copy, readonly) NSString *speech AI_DEPRECATED_MSG_ATTRIBUTE("Use messages property."); + +/** + Response messages. See https://docs.api.ai/docs/rich-messages for details. + */ +@property(nonatomic, copy, readonly) NSArray AI_GENERICS_1(NSDictionary *) *messages; @end diff --git a/ApiAI/Response/Classes/AIResponseFulfillment.m b/ApiAI/Response/Classes/AIResponseFulfillment.m index 62c2441..84c337c 100644 --- a/ApiAI/Response/Classes/AIResponseFulfillment.m +++ b/ApiAI/Response/Classes/AIResponseFulfillment.m @@ -29,6 +29,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dictionary self = [super init]; if (self) { _speech = dictionary[@"speech"]; + _messages = dictionary[@"messages"]; } return self; diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m index 1f653ed..beeb78f 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m @@ -93,7 +93,7 @@ - (void)prepare { NSMutableURLRequest *request = self.prepareDefaultRequest; [request addValue:@"100-continue" forHTTPHeaderField:@"Expect"]; -// [request addValue:@"close" forHTTPHeaderField:@"Connection"]; + [request addValue:@"close" forHTTPHeaderField:@"Connection"]; request.HTTPShouldUsePipelining = YES; From 6737aa4617c608cc429b941373dcc5feb3a3ba3b Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 13:31:38 +0700 Subject: [PATCH 05/13] fixes for events and tests for events. --- ApiAI.xcodeproj/project.pbxproj | 4 ++ .../xcschemes/ApiAITests.xcscheme | 3 + ApiAI/Classes/ApiAI.h | 8 +++ ApiAI/Classes/ApiAI.m | 12 ++++ ApiAI/EventRequest/AIEvent.h | 6 +- ApiAI/EventRequest/AIEvent.m | 8 +-- ApiAI/EventRequest/AIEventRequest.m | 4 +- ApiAITests/EventsTests.m | 65 +++++++++++++++++++ 8 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 ApiAITests/EventsTests.m diff --git a/ApiAI.xcodeproj/project.pbxproj b/ApiAI.xcodeproj/project.pbxproj index 54d020e..9314812 100644 --- a/ApiAI.xcodeproj/project.pbxproj +++ b/ApiAI.xcodeproj/project.pbxproj @@ -155,6 +155,7 @@ 5865DD1F1DFA7CD00073D1A3 /* AIEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */; }; 5865DD201DFA7E4A0073D1A3 /* AIEventRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */; }; 5865DD211DFA7E4A0073D1A3 /* AIEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */; }; + 5865DD271DFA82400073D1A3 /* EventsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5865DD261DFA82400073D1A3 /* EventsTests.m */; }; 5867737D1BD0F76000E1253D /* speech_d.wav in Resources */ = {isa = PBXBuildFile; fileRef = 5867737C1BD0F76000E1253D /* speech_d.wav */; }; 5869BCFD1B37E56A000B99B7 /* AINullabilityDefines.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 5869BCFC1B37E505000B99B7 /* AINullabilityDefines.h */; }; 587074061CA184C900C4535B /* AIVoiceRequestButton.xib in Resources */ = {isa = PBXBuildFile; fileRef = 581AB39E1A245D8300E8A190 /* AIVoiceRequestButton.xib */; }; @@ -315,6 +316,7 @@ 5865DD1B1DFA7CA50073D1A3 /* AIEventRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIEventRequest.m; sourceTree = ""; }; 5865DD1D1DFA7CD00073D1A3 /* AIEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIEvent.h; sourceTree = ""; }; 5865DD1E1DFA7CD00073D1A3 /* AIEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIEvent.m; sourceTree = ""; }; + 5865DD261DFA82400073D1A3 /* EventsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventsTests.m; sourceTree = ""; }; 5867737C1BD0F76000E1253D /* speech_d.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = speech_d.wav; sourceTree = ""; }; 5869BCFC1B37E505000B99B7 /* AINullabilityDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AINullabilityDefines.h; sourceTree = ""; }; 588D23831AFB3C95008289F1 /* AIResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIResponse.h; sourceTree = ""; }; @@ -843,6 +845,7 @@ 58F0604D1A8CB366002615DF /* ApiAITests.m */, 58AA07AD1B39494900A259D9 /* AIVADTest.m */, 581409F71C86C7E30014BBE8 /* UserEntitiesTests.m */, + 5865DD261DFA82400073D1A3 /* EventsTests.m */, 58F0604B1A8CB366002615DF /* Supporting Files */, ); path = ApiAITests; @@ -1224,6 +1227,7 @@ 588D23AF1AFB3F24008289F1 /* AIRequest+AIMappedResponse.m in Sources */, 581409F81C86C7E30014BBE8 /* UserEntitiesTests.m in Sources */, 588D23A91AFB3CAB008289F1 /* AIDatePeriodFormatter.m in Sources */, + 5865DD271DFA82400073D1A3 /* EventsTests.m in Sources */, 588D23A41AFB3CA1008289F1 /* AIResponseFulfillment.m in Sources */, 588D23A81AFB3CA1008289F1 /* AIResponseStatus.m in Sources */, 588D23A61AFB3CA1008289F1 /* AIResponseParameter.m in Sources */, diff --git a/ApiAI.xcodeproj/xcshareddata/xcschemes/ApiAITests.xcscheme b/ApiAI.xcodeproj/xcshareddata/xcschemes/ApiAITests.xcscheme index 1d4447f..c6dd1c2 100644 --- a/ApiAI.xcodeproj/xcshareddata/xcschemes/ApiAITests.xcscheme +++ b/ApiAI.xcodeproj/xcshareddata/xcschemes/ApiAITests.xcscheme @@ -44,6 +44,9 @@ + + diff --git a/ApiAI/Classes/ApiAI.h b/ApiAI/Classes/ApiAI.h index cf9a566..cd7be5a 100644 --- a/ApiAI/Classes/ApiAI.h +++ b/ApiAI/Classes/ApiAI.h @@ -55,6 +55,10 @@ #import "AIUserEntitiesRequest.h" #endif +#if __has_include("AIEventRequest.h") + #import "AIEventRequest.h" +#endif + /*! @enum AIRequestType enum @@ -174,6 +178,10 @@ typedef NS_ENUM(NSUInteger, AIRequestType) { - (AIVoiceFileRequest *)voiceFileRequestWithData:(NSData *)fileData AI_DEPRECATED_MSG_ATTRIBUTE("Will be removed on 1 Feb 2016."); #endif +#if __has_include("AIEventRequest.h") +- (AIEventRequest *)eventRequest; +#endif + /*! @method enqueue diff --git a/ApiAI/Classes/ApiAI.m b/ApiAI/Classes/ApiAI.m index 635fcd7..b9e12cf 100644 --- a/ApiAI/Classes/ApiAI.m +++ b/ApiAI/Classes/ApiAI.m @@ -146,6 +146,18 @@ - (AIVoiceFileRequest *)voiceFileRequestWithData:(NSData *)fileData #endif +#if __has_include("AIEventRequest.h") +- (AIEventRequest *)eventRequest +{ + AIEventRequest *request = [[AIEventRequest alloc] initWithDataService:_dataService]; + + [request setVersion:self.version]; + [request setLang:self.lang]; + + return request; +} +#endif + - (void)setConfiguration:(id)configuration { _configuration = configuration; diff --git a/ApiAI/EventRequest/AIEvent.h b/ApiAI/EventRequest/AIEvent.h index 88ccf3c..f078ef7 100644 --- a/ApiAI/EventRequest/AIEvent.h +++ b/ApiAI/EventRequest/AIEvent.h @@ -10,10 +10,10 @@ @interface AIEvent : NSObject -@property(nonatomic, copy) NSString *event; +@property(nonatomic, copy) NSString *name; @property(nonatomic, copy) NSDictionary *data; -- (instancetype)initWithEvent:(NSString *)event andData:(NSDictionary *)data; -- (instancetype)initWithEvent:(NSString *)event; +- (instancetype)initWithName:(NSString *)name andData:(NSDictionary *)data; +- (instancetype)initWithName:(NSString *)name; @end diff --git a/ApiAI/EventRequest/AIEvent.m b/ApiAI/EventRequest/AIEvent.m index b33d924..3a0ac89 100644 --- a/ApiAI/EventRequest/AIEvent.m +++ b/ApiAI/EventRequest/AIEvent.m @@ -10,20 +10,20 @@ @implementation AIEvent -- (instancetype)initWithEvent:(NSString *)event andData:(NSDictionary *)data { +- (instancetype)initWithName:(NSString *)name andData:(NSDictionary *)data { self = [super init]; if (self) { - self.event = event; + self.name = name; self.data = data; } return self; } -- (instancetype)initWithEvent:(NSString *)event { +- (instancetype)initWithName:(NSString *)name { self = [super init]; if (self) { - self.event = event; + self.name = name; self.data = nil; } return self; diff --git a/ApiAI/EventRequest/AIEventRequest.m b/ApiAI/EventRequest/AIEventRequest.m index 9131749..c761b76 100644 --- a/ApiAI/EventRequest/AIEventRequest.m +++ b/ApiAI/EventRequest/AIEventRequest.m @@ -33,8 +33,8 @@ - (void)configureHTTPRequest { NSString *timeZoneString = self.timeZone ? self.timeZone.name : [NSTimeZone localTimeZone].name; NSDictionary *eventDictionary = @{ - @"event": _event.event, - @"data": _event.data + @"name": _event.name ?: @"", + @"data": _event.data ?: @{} }; NSMutableDictionary *parameters = [@{ diff --git a/ApiAITests/EventsTests.m b/ApiAITests/EventsTests.m new file mode 100644 index 0000000..1f36857 --- /dev/null +++ b/ApiAITests/EventsTests.m @@ -0,0 +1,65 @@ +// +// EventsTests.m +// ApiAI +// +// Created by Kuragin Dmitriy on 09/12/2016. +// Copyright © 2016 Kuragin Dmitriy. All rights reserved. +// + +#import + +#import "ApiAI.h" +#import "AIDefaultConfiguration.h" +#import "AIResponse.h" +#import "AIRequestEntity.h" +#import "AIUserEntitiesRequest.h" + +@interface EventsTests : XCTestCase + +@property(nonatomic, strong) ApiAI *apiai; + +@end + + +@implementation EventsTests + +- (void)setUp { + [super setUp]; + + ApiAI *apiai = [ApiAI sharedApiAI]; + + AIDefaultConfiguration *configuration = [[AIDefaultConfiguration alloc] init]; + + configuration.clientAccessToken = @"09604c7f91ce4cd8a4ede55eb5340b9d"; + + [apiai setConfiguration:configuration]; + + apiai.lang = @"en"; + + self.apiai = apiai; +} + +- (void)testEvents { + XCTestExpectation *expectationEventRequest = [self expectationWithDescription:@"Event request."]; + + AIEventRequest *eventRequest = _apiai.eventRequest; + + eventRequest.event = [[AIEvent alloc] initWithName:@"my_custom_event"]; + + [eventRequest setMappedCompletionBlockSuccess:^(AIRequest *request, AIResponse *response) { + XCTAssert([response.result.action isEqualToString:@"my_custom_event.some_action"], @"error"); + + [expectationEventRequest fulfill]; + } failure:^(AIRequest *request, NSError *error) { + XCTAssert(NO, @"Send event request with error."); + [expectationEventRequest fulfill]; + }]; + + [_apiai enqueue:eventRequest]; + + [self waitForExpectationsWithTimeout:60 handler:^(NSError * _Nullable error) { + XCTAssertNil(error, @"Error"); + }]; +} + +@end From 2813c46719d5b572992ed255034d595a95a77365 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 14:21:54 +0700 Subject: [PATCH 06/13] fix pod. --- ApiAI.podspec.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApiAI.podspec.json b/ApiAI.podspec.json index 122042f..0bf01c4 100644 --- a/ApiAI.podspec.json +++ b/ApiAI.podspec.json @@ -228,7 +228,7 @@ "name": "Events", "source_files": [ - "ApiAI/EventRequest/**/*.{h,m,c}", + "ApiAI/EventRequest/**/*.{h,m,c}" ], "resources": [], From 49d3321575e506ce7e483b1f258e54efbc0c97c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 14:22:11 +0700 Subject: [PATCH 07/13] version 0.6.1 --- ApiAI.podspec.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApiAI.podspec.json b/ApiAI.podspec.json index 0bf01c4..1c9da07 100644 --- a/ApiAI.podspec.json +++ b/ApiAI.podspec.json @@ -1,6 +1,6 @@ { "name": "ApiAI", - "version": "0.6.0", + "version": "0.6.1", "license": "Apache 2.0", "summary": "The API.AI iOS SDK makes it easy to integrate speech recognition with API.AI natural language processing API on iOS devices.", "homepage": "http://api.ai/", @@ -10,7 +10,7 @@ "source": { "git": "https://github.com/api-ai/api-ai-ios-sdk.git", - "tag": "v0.6.0" + "tag": "v0.6.1" }, "requires_arc": true, From 339eda1d5430320b16f78da41205b66093f7aaa2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Fri, 9 Dec 2016 14:33:06 +0700 Subject: [PATCH 08/13] version 0.6.2 --- ApiAI.podspec.json | 4 ++-- ApiAI/UIKit/Private/AIEllipseView.m | 1 + ApiAI/UIKit/Private/AIProgressView.m | 2 ++ ApiAI/VoiceRequest/Classes/AIVoiceRequest.m | 20 ++++++++++---------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ApiAI.podspec.json b/ApiAI.podspec.json index 1c9da07..185d4ea 100644 --- a/ApiAI.podspec.json +++ b/ApiAI.podspec.json @@ -1,6 +1,6 @@ { "name": "ApiAI", - "version": "0.6.1", + "version": "0.6.2", "license": "Apache 2.0", "summary": "The API.AI iOS SDK makes it easy to integrate speech recognition with API.AI natural language processing API on iOS devices.", "homepage": "http://api.ai/", @@ -10,7 +10,7 @@ "source": { "git": "https://github.com/api-ai/api-ai-ios-sdk.git", - "tag": "v0.6.1" + "tag": "v0.6.2" }, "requires_arc": true, diff --git a/ApiAI/UIKit/Private/AIEllipseView.m b/ApiAI/UIKit/Private/AIEllipseView.m index 20aa5e7..f722288 100644 --- a/ApiAI/UIKit/Private/AIEllipseView.m +++ b/ApiAI/UIKit/Private/AIEllipseView.m @@ -88,6 +88,7 @@ @implementation AIEllipseView - (void)awakeFromNib { + [super awakeFromNib]; self.layer.contentsScale = [UIScreen mainScreen].scale; } diff --git a/ApiAI/UIKit/Private/AIProgressView.m b/ApiAI/UIKit/Private/AIProgressView.m index 49d86ba..aaa954d 100644 --- a/ApiAI/UIKit/Private/AIProgressView.m +++ b/ApiAI/UIKit/Private/AIProgressView.m @@ -110,6 +110,8 @@ - (void)setColor:(UIColor *)color - (void)awakeFromNib { + [super awakeFromNib]; + AIProgressLayer *layer = (AIProgressLayer *)self.layer; layer.contentsScale = [UIScreen mainScreen].scale; } diff --git a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m index beeb78f..0c3f5db 100644 --- a/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m +++ b/ApiAI/VoiceRequest/Classes/AIVoiceRequest.m @@ -262,15 +262,15 @@ - (NSString *)creteBoundary + (void)createBoundInputStream:(NSInputStream **)inputStreamPtr outputStream:(NSOutputStream **)outputStreamPtr bufferSize:(NSUInteger)bufferSize { - if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) { - NSInputStream *input = NULL; - NSOutputStream *output = NULL; - - [NSStream getBoundStreamsWithBufferSize:bufferSize inputStream:&input outputStream:&output]; - - *inputStreamPtr = input; - *outputStreamPtr = output; - } else { +// if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) { +// NSInputStream *input = NULL; +// NSOutputStream *output = NULL; +// +// [NSStream getBoundStreamsWithBufferSize:bufferSize inputStream:&input outputStream:&output]; +// +// *inputStreamPtr = input; +// *outputStreamPtr = output; +// } else { CFReadStreamRef readStream; CFWriteStreamRef writeStream; @@ -292,7 +292,7 @@ + (void)createBoundInputStream:(NSInputStream **)inputStreamPtr outputStream:(NS if (outputStreamPtr != NULL) { *outputStreamPtr = CFBridgingRelease(writeStream); } - } +// } } - (void)recordDetector:(AIRecordDetector *)helper didReceiveData:(NSData *)data power:(float)power From 8754127e34ea75018680203c653ac0c5541876df Mon Sep 17 00:00:00 2001 From: Dmitriy Kuragin Date: Thu, 22 Dec 2016 11:19:42 +0700 Subject: [PATCH 09/13] migrate swift example to lates swift version. --- .../ApiAIDemoSwift.xcodeproj/project.pbxproj | 26 ++++++++------ .../ApiAIDemoSwift/AppDelegate.swift | 16 ++++----- .../ResultViewController.swift | 6 ++-- .../SimpleVoiceRequestController.swift | 34 +++++++++---------- .../TextRequestViewController.swift | 24 ++++++------- .../VoiceButtonViewController.swift | 14 ++++---- .../ApiAIDemoSwiftTests.swift | 2 +- 7 files changed, 63 insertions(+), 59 deletions(-) diff --git a/ApiAIDemoSwift/ApiAIDemoSwift.xcodeproj/project.pbxproj b/ApiAIDemoSwift/ApiAIDemoSwift.xcodeproj/project.pbxproj index 55319d4..574f457 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift.xcodeproj/project.pbxproj +++ b/ApiAIDemoSwift/ApiAIDemoSwift.xcodeproj/project.pbxproj @@ -192,12 +192,12 @@ isa = PBXNativeTarget; buildConfigurationList = 5875124E1AC275280053EAA9 /* Build configuration list for PBXNativeTarget "ApiAIDemoSwift" */; buildPhases = ( - 30E3F8442E8F846FC50DD577 /* 📦 Check Pods Manifest.lock */, + 30E3F8442E8F846FC50DD577 /* [CP] Check Pods Manifest.lock */, 5875122B1AC275280053EAA9 /* Sources */, 5875122C1AC275280053EAA9 /* Frameworks */, 5875122D1AC275280053EAA9 /* Resources */, - 8EE6E255B94C1A06C5244429 /* 📦 Embed Pods Frameworks */, - E281031366BE97EF229CB865 /* 📦 Copy Pods Resources */, + 8EE6E255B94C1A06C5244429 /* [CP] Embed Pods Frameworks */, + E281031366BE97EF229CB865 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -238,9 +238,11 @@ TargetAttributes = { 5875122E1AC275280053EAA9 = { CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0820; }; 587512431AC275280053EAA9 = { CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0820; TestTargetID = 5875122E1AC275280053EAA9; }; }; @@ -285,29 +287,29 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 30E3F8442E8F846FC50DD577 /* 📦 Check Pods Manifest.lock */ = { + 30E3F8442E8F846FC50DD577 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 8EE6E255B94C1A06C5244429 /* 📦 Embed Pods Frameworks */ = { + 8EE6E255B94C1A06C5244429 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -315,14 +317,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ApiAIDemoSwift/Pods-ApiAIDemoSwift-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - E281031366BE97EF229CB865 /* 📦 Copy Pods Resources */ = { + E281031366BE97EF229CB865 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -475,6 +477,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "ApiAIDemoSwift/ApiAIDemoSwift-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -489,6 +492,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.speaktoit.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "ApiAIDemoSwift/ApiAIDemoSwift-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -508,6 +512,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.speaktoit.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ApiAIDemoSwift.app/ApiAIDemoSwift"; }; name = Debug; @@ -524,6 +529,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.speaktoit.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ApiAIDemoSwift.app/ApiAIDemoSwift"; }; name = Release; diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/AppDelegate.swift b/ApiAIDemoSwift/ApiAIDemoSwift/AppDelegate.swift index fb8bdb4..9d3d030 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/AppDelegate.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwift/AppDelegate.swift @@ -12,11 +12,11 @@ import AVFoundation @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - let apiai = ApiAI.sharedApiAI() + let apiai = ApiAI.shared()! var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { let session = AVAudioSession.sharedInstance() @@ -26,8 +26,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } catch { // same error } - - let apiai = ApiAI.sharedApiAI() let configuration: AIConfiguration = AIDefaultConfiguration() @@ -40,25 +38,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/ResultViewController/ResultViewController.swift b/ApiAIDemoSwift/ApiAIDemoSwift/ResultViewController/ResultViewController.swift index 0498845..c860b1e 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/ResultViewController/ResultViewController.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwift/ResultViewController/ResultViewController.swift @@ -9,7 +9,7 @@ import UIKit class ResultViewController: UIViewController { - @IBOutlet private var textView: UITextView? = nil + @IBOutlet fileprivate var textView: UITextView? = nil var response: AnyObject? = nil @@ -19,7 +19,7 @@ class ResultViewController: UIViewController { self.textView?.text = self.response?.description } - @IBAction func done(sender: UIBarButtonItem) { - self.dismissViewControllerAnimated(true, completion: nil) + @IBAction func done(_ sender: UIBarButtonItem) { + self.dismiss(animated: true, completion: nil) } } diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/SimpleVoiceRequestController/SimpleVoiceRequestController.swift b/ApiAIDemoSwift/ApiAIDemoSwift/SimpleVoiceRequestController/SimpleVoiceRequestController.swift index f764ac0..3aa3567 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/SimpleVoiceRequestController/SimpleVoiceRequestController.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwift/SimpleVoiceRequestController/SimpleVoiceRequestController.swift @@ -23,23 +23,23 @@ class SimpleVoiceRequestController: UIViewController { self.changeStateToStop() } - @IBAction func startListening(sender: UIButton) { + @IBAction func startListening(_ sender: UIButton) { self.changeStateToListening() - let apiai = ApiAI.sharedApiAI() + let apiai = ApiAI.shared() - let request = apiai.voiceRequest() + let request = apiai?.voiceRequest() if let vad = self.useVAD { - request.useVADForAutoCommit = vad.on + request?.useVADForAutoCommit = vad.isOn } - request.setCompletionBlockSuccess({[unowned self] (request, response) -> Void in - let resultNavigationController = self.storyboard?.instantiateViewControllerWithIdentifier("ResultViewController") as! ResultNavigationController + request?.setCompletionBlockSuccess({[unowned self] (request, response) -> Void in + let resultNavigationController = self.storyboard?.instantiateViewController(withIdentifier: "ResultViewController") as! ResultNavigationController - resultNavigationController.response = response + resultNavigationController.response = response as AnyObject? - self.presentViewController(resultNavigationController, animated: true, completion: nil) + self.present(resultNavigationController, animated: true, completion: nil) self.changeStateToStop() @@ -49,14 +49,14 @@ class SimpleVoiceRequestController: UIViewController { self.currentVoiceRequest = request - apiai.enqueue(request) + apiai?.enqueue(request) } - @IBAction func stopListening(sender: UIButton) { + @IBAction func stopListening(_ sender: UIButton) { self.currentVoiceRequest?.commitVoice() } - override func viewWillDisappear(animated: Bool) { + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.currentVoiceRequest?.cancel() @@ -64,18 +64,18 @@ class SimpleVoiceRequestController: UIViewController { func changeStateToStop() { self.activity?.stopAnimating() - self.startListeningButton?.enabled = true - self.stopListeningButton?.enabled = false + self.startListeningButton?.isEnabled = true + self.stopListeningButton?.isEnabled = false - self.useVAD?.enabled = true + self.useVAD?.isEnabled = true } func changeStateToListening() { self.activity?.startAnimating() - self.startListeningButton?.enabled = false - self.stopListeningButton?.enabled = true + self.startListeningButton?.isEnabled = false + self.stopListeningButton?.isEnabled = true - self.useVAD?.enabled = false + self.useVAD?.isEnabled = false } } diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/TextRequestViewController/TextRequestViewController.swift b/ApiAIDemoSwift/ApiAIDemoSwift/TextRequestViewController/TextRequestViewController.swift index 3bf093d..ccbd112 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/TextRequestViewController/TextRequestViewController.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwift/TextRequestViewController/TextRequestViewController.swift @@ -11,32 +11,32 @@ import UIKit class TextRequestViewController: UIViewController { @IBOutlet var textField: UITextField? = nil - @IBAction func sendText(sender: UIButton) + @IBAction func sendText(_ sender: UIButton) { - let hud = MBProgressHUD.showHUDAddedTo(self.view.window!, animated: true) + let hud = MBProgressHUD.showAdded(to: self.view.window!, animated: true) self.textField?.resignFirstResponder() - let request = ApiAI.sharedApiAI().textRequest() + let request = ApiAI.shared().textRequest() if let text = self.textField?.text { - request.query = [text] + request?.query = [text] } else { - request.query = [""] + request?.query = [""] } - request.setCompletionBlockSuccess({[unowned self] (request, response) -> Void in - let resultNavigationController = self.storyboard?.instantiateViewControllerWithIdentifier("ResultViewController") as! ResultNavigationController + request?.setCompletionBlockSuccess({[unowned self] (request, response) -> Void in + let resultNavigationController = self.storyboard?.instantiateViewController(withIdentifier: "ResultViewController") as! ResultNavigationController - resultNavigationController.response = response + resultNavigationController.response = response as AnyObject? - self.presentViewController(resultNavigationController, animated: true, completion: nil) + self.present(resultNavigationController, animated: true, completion: nil) - hud.hideAnimated(true) + hud.hide(animated: true) }, failure: { (request, error) -> Void in - hud.hideAnimated(true) + hud.hide(animated: true) }); - ApiAI.sharedApiAI().enqueue(request) + ApiAI.shared().enqueue(request) } } diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/VoiceButtonRequest/VoiceButtonViewController.swift b/ApiAIDemoSwift/ApiAIDemoSwift/VoiceButtonRequest/VoiceButtonViewController.swift index 12daf34..3e8d5ba 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/VoiceButtonRequest/VoiceButtonViewController.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwift/VoiceButtonRequest/VoiceButtonViewController.swift @@ -10,25 +10,25 @@ import UIKit class VoiceButtonViewController: UIViewController { - @IBOutlet var voiceRequestButton: AIVoiceRequestButton? = nil + @IBOutlet var voiceRequestButton: AIVoiceRequestButton! override func viewDidLoad() { super.viewDidLoad() - self.voiceRequestButton?.successCallback = {(response) -> Void in - self.showResult(response) + self.voiceRequestButton.successCallback = {(response) -> Void in + } - self.voiceRequestButton?.failureCallback = {(error) -> Void in + self.voiceRequestButton.failureCallback = {(error) -> Void in } } - func showResult(response: AnyObject) { - let resultNavigationController = self.storyboard?.instantiateViewControllerWithIdentifier("ResultViewController") as! ResultNavigationController + func showResult(_ response: AnyObject) { + let resultNavigationController = self.storyboard?.instantiateViewController(withIdentifier: "ResultViewController") as! ResultNavigationController resultNavigationController.response = response - self.presentViewController(resultNavigationController, animated: true, completion: nil) + self.present(resultNavigationController, animated: true, completion: nil) } } diff --git a/ApiAIDemoSwift/ApiAIDemoSwiftTests/ApiAIDemoSwiftTests.swift b/ApiAIDemoSwift/ApiAIDemoSwiftTests/ApiAIDemoSwiftTests.swift index eed76d5..ceb6593 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwiftTests/ApiAIDemoSwiftTests.swift +++ b/ApiAIDemoSwift/ApiAIDemoSwiftTests/ApiAIDemoSwiftTests.swift @@ -28,7 +28,7 @@ class ApiAIDemoSwiftTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock() { + self.measure() { // Put the code you want to measure the time of here. } } From 364b16f9a1d5bc219762da6a3a40d4e5b900ebec Mon Sep 17 00:00:00 2001 From: Grant Kemp Date: Tue, 3 Jan 2017 02:31:40 +0000 Subject: [PATCH 10/13] bugfix: Added Microphone Info plist entry to give the user the correct warning and remove the error being generated by IOS --- ApiAIDemoSwift/ApiAIDemoSwift/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApiAIDemoSwift/ApiAIDemoSwift/Info.plist b/ApiAIDemoSwift/ApiAIDemoSwift/Info.plist index 6905cc6..0ec1b38 100644 --- a/ApiAIDemoSwift/ApiAIDemoSwift/Info.plist +++ b/ApiAIDemoSwift/ApiAIDemoSwift/Info.plist @@ -2,6 +2,8 @@ + NSMicrophoneUsageDescription + This is used to allow you to make voice requests CFBundleDevelopmentRegion en CFBundleExecutable From c28602fc76ebaa091f3939d34b4ff3e2c3a9cfe2 Mon Sep 17 00:00:00 2001 From: Grant Kemp Date: Tue, 3 Jan 2017 02:35:03 +0000 Subject: [PATCH 11/13] feature: added MacOS Swift port to learn how the SDK works and to help others using the SDK. Enhancement: Changed the behaviour of the response to also output to a large text field so developers can copy and paste the output straight from the app to other tools on mac which should improve development time and make it easier to build apps. --- .../project.pbxproj | 547 +++++++++++++ .../APIAiMacOSSwiftDemo/AppDelegate.swift | 31 + .../AppIcon.appiconset/Contents.json | 58 ++ .../Base.lproj/Main.storyboard | 742 ++++++++++++++++++ .../APIAiMacOSSwiftDemo/Info.plist | 32 + .../APIAiMacOSSwiftDemo/ViewController.swift | 57 ++ .../APIAiMacOSSwiftDemoTests.swift | 36 + .../APIAiMacOSSwiftDemoTests/Info.plist | 22 + ApiAIMacOSDemoSwift/Podfile | 19 + 9 files changed, 1544 insertions(+) create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcodeproj/project.pbxproj create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/AppDelegate.swift create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Base.lproj/Main.storyboard create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Info.plist create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/ViewController.swift create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/APIAiMacOSSwiftDemoTests.swift create mode 100644 ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/Info.plist create mode 100644 ApiAIMacOSDemoSwift/Podfile diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcodeproj/project.pbxproj b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fbaa7d0 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcodeproj/project.pbxproj @@ -0,0 +1,547 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1EA06300F856E3DAB8021081 /* Pods_APIAiMacOSSwiftDemoTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E119C44264CEAB6993924E94 /* Pods_APIAiMacOSSwiftDemoTests.framework */; }; + 5ABE48E659C5D31F5EC9B64C /* Pods_APIAiMacOSSwiftDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5D0EB0A9C5FCC5E58D3E45 /* Pods_APIAiMacOSSwiftDemo.framework */; }; + A1C11CDA1E1B2CC400D7E943 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C11CD91E1B2CC400D7E943 /* AppDelegate.swift */; }; + A1C11CDC1E1B2CC400D7E943 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C11CDB1E1B2CC400D7E943 /* ViewController.swift */; }; + A1C11CDE1E1B2CC400D7E943 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1C11CDD1E1B2CC400D7E943 /* Assets.xcassets */; }; + A1C11CE11E1B2CC400D7E943 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A1C11CDF1E1B2CC400D7E943 /* Main.storyboard */; }; + A1C11CEC1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C11CEB1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + A1C11CE81E1B2CC400D7E943 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A1C11CCE1E1B2CC400D7E943 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A1C11CD51E1B2CC400D7E943; + remoteInfo = APIAiMacOSSwiftDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 5759CB0930E097F0EEF996BB /* Pods-APIAiMacOSSwiftDemoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIAiMacOSSwiftDemoTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIAiMacOSSwiftDemoTests/Pods-APIAiMacOSSwiftDemoTests.release.xcconfig"; sourceTree = ""; }; + 5B5D0EB0A9C5FCC5E58D3E45 /* Pods_APIAiMacOSSwiftDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APIAiMacOSSwiftDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A1C11CD61E1B2CC400D7E943 /* APIAiMacOSSwiftDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = APIAiMacOSSwiftDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A1C11CD91E1B2CC400D7E943 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A1C11CDB1E1B2CC400D7E943 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + A1C11CDD1E1B2CC400D7E943 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A1C11CE01E1B2CC400D7E943 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + A1C11CE21E1B2CC400D7E943 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A1C11CE71E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APIAiMacOSSwiftDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + A1C11CEB1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIAiMacOSSwiftDemoTests.swift; sourceTree = ""; }; + A1C11CED1E1B2CC400D7E943 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E119C44264CEAB6993924E94 /* Pods_APIAiMacOSSwiftDemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APIAiMacOSSwiftDemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E8DC645F30E438A1D49FDED9 /* Pods-APIAiMacOSSwiftDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIAiMacOSSwiftDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIAiMacOSSwiftDemo/Pods-APIAiMacOSSwiftDemo.release.xcconfig"; sourceTree = ""; }; + F2EA4C0D804749B1565D745C /* Pods-APIAiMacOSSwiftDemoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIAiMacOSSwiftDemoTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APIAiMacOSSwiftDemoTests/Pods-APIAiMacOSSwiftDemoTests.debug.xcconfig"; sourceTree = ""; }; + F8FF9F2B06DB8006866D79BA /* Pods-APIAiMacOSSwiftDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIAiMacOSSwiftDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APIAiMacOSSwiftDemo/Pods-APIAiMacOSSwiftDemo.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A1C11CD31E1B2CC400D7E943 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5ABE48E659C5D31F5EC9B64C /* Pods_APIAiMacOSSwiftDemo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1C11CE41E1B2CC400D7E943 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EA06300F856E3DAB8021081 /* Pods_APIAiMacOSSwiftDemoTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 16CF39B62B51494A88D503A2 /* Pods */ = { + isa = PBXGroup; + children = ( + F8FF9F2B06DB8006866D79BA /* Pods-APIAiMacOSSwiftDemo.debug.xcconfig */, + E8DC645F30E438A1D49FDED9 /* Pods-APIAiMacOSSwiftDemo.release.xcconfig */, + F2EA4C0D804749B1565D745C /* Pods-APIAiMacOSSwiftDemoTests.debug.xcconfig */, + 5759CB0930E097F0EEF996BB /* Pods-APIAiMacOSSwiftDemoTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 55AE6D24BA9374F57D911F37 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5B5D0EB0A9C5FCC5E58D3E45 /* Pods_APIAiMacOSSwiftDemo.framework */, + E119C44264CEAB6993924E94 /* Pods_APIAiMacOSSwiftDemoTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A1C11CCD1E1B2CC400D7E943 = { + isa = PBXGroup; + children = ( + A1C11CD81E1B2CC400D7E943 /* APIAiMacOSSwiftDemo */, + A1C11CEA1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests */, + A1C11CD71E1B2CC400D7E943 /* Products */, + 16CF39B62B51494A88D503A2 /* Pods */, + 55AE6D24BA9374F57D911F37 /* Frameworks */, + ); + sourceTree = ""; + }; + A1C11CD71E1B2CC400D7E943 /* Products */ = { + isa = PBXGroup; + children = ( + A1C11CD61E1B2CC400D7E943 /* APIAiMacOSSwiftDemo.app */, + A1C11CE71E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + A1C11CD81E1B2CC400D7E943 /* APIAiMacOSSwiftDemo */ = { + isa = PBXGroup; + children = ( + A1C11CD91E1B2CC400D7E943 /* AppDelegate.swift */, + A1C11CDB1E1B2CC400D7E943 /* ViewController.swift */, + A1C11CDD1E1B2CC400D7E943 /* Assets.xcassets */, + A1C11CDF1E1B2CC400D7E943 /* Main.storyboard */, + A1C11CE21E1B2CC400D7E943 /* Info.plist */, + ); + path = APIAiMacOSSwiftDemo; + sourceTree = ""; + }; + A1C11CEA1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests */ = { + isa = PBXGroup; + children = ( + A1C11CEB1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.swift */, + A1C11CED1E1B2CC400D7E943 /* Info.plist */, + ); + path = APIAiMacOSSwiftDemoTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A1C11CD51E1B2CC400D7E943 /* APIAiMacOSSwiftDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1C11CF01E1B2CC400D7E943 /* Build configuration list for PBXNativeTarget "APIAiMacOSSwiftDemo" */; + buildPhases = ( + 496C1CC4A32D409BD5C2CA45 /* [CP] Check Pods Manifest.lock */, + A1C11CD21E1B2CC400D7E943 /* Sources */, + A1C11CD31E1B2CC400D7E943 /* Frameworks */, + A1C11CD41E1B2CC400D7E943 /* Resources */, + EA78B4AFEC5F10E1736403E5 /* [CP] Embed Pods Frameworks */, + 3D057C098294E2E27EF3D496 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = APIAiMacOSSwiftDemo; + productName = APIAiMacOSSwiftDemo; + productReference = A1C11CD61E1B2CC400D7E943 /* APIAiMacOSSwiftDemo.app */; + productType = "com.apple.product-type.application"; + }; + A1C11CE61E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1C11CF31E1B2CC400D7E943 /* Build configuration list for PBXNativeTarget "APIAiMacOSSwiftDemoTests" */; + buildPhases = ( + 4EEF9D5CA7BC3FF2C7F30892 /* [CP] Check Pods Manifest.lock */, + A1C11CE31E1B2CC400D7E943 /* Sources */, + A1C11CE41E1B2CC400D7E943 /* Frameworks */, + A1C11CE51E1B2CC400D7E943 /* Resources */, + 6238518689010A975E818EEF /* [CP] Embed Pods Frameworks */, + 7574FB6BD6B9311F8AF04948 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + A1C11CE91E1B2CC400D7E943 /* PBXTargetDependency */, + ); + name = APIAiMacOSSwiftDemoTests; + productName = APIAiMacOSSwiftDemoTests; + productReference = A1C11CE71E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A1C11CCE1E1B2CC400D7E943 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Grant Kemp"; + TargetAttributes = { + A1C11CD51E1B2CC400D7E943 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + A1C11CE61E1B2CC400D7E943 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + TestTargetID = A1C11CD51E1B2CC400D7E943; + }; + }; + }; + buildConfigurationList = A1C11CD11E1B2CC400D7E943 /* Build configuration list for PBXProject "APIAiMacOSSwiftDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A1C11CCD1E1B2CC400D7E943; + productRefGroup = A1C11CD71E1B2CC400D7E943 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A1C11CD51E1B2CC400D7E943 /* APIAiMacOSSwiftDemo */, + A1C11CE61E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A1C11CD41E1B2CC400D7E943 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1C11CDE1E1B2CC400D7E943 /* Assets.xcassets in Resources */, + A1C11CE11E1B2CC400D7E943 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1C11CE51E1B2CC400D7E943 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3D057C098294E2E27EF3D496 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIAiMacOSSwiftDemo/Pods-APIAiMacOSSwiftDemo-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 496C1CC4A32D409BD5C2CA45 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 4EEF9D5CA7BC3FF2C7F30892 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 6238518689010A975E818EEF /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIAiMacOSSwiftDemoTests/Pods-APIAiMacOSSwiftDemoTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7574FB6BD6B9311F8AF04948 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIAiMacOSSwiftDemoTests/Pods-APIAiMacOSSwiftDemoTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + EA78B4AFEC5F10E1736403E5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIAiMacOSSwiftDemo/Pods-APIAiMacOSSwiftDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A1C11CD21E1B2CC400D7E943 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1C11CDC1E1B2CC400D7E943 /* ViewController.swift in Sources */, + A1C11CDA1E1B2CC400D7E943 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1C11CE31E1B2CC400D7E943 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1C11CEC1E1B2CC400D7E943 /* APIAiMacOSSwiftDemoTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A1C11CE91E1B2CC400D7E943 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A1C11CD51E1B2CC400D7E943 /* APIAiMacOSSwiftDemo */; + targetProxy = A1C11CE81E1B2CC400D7E943 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + A1C11CDF1E1B2CC400D7E943 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A1C11CE01E1B2CC400D7E943 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A1C11CEE1E1B2CC400D7E943 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A1C11CEF1E1B2CC400D7E943 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + A1C11CF11E1B2CC400D7E943 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F8FF9F2B06DB8006866D79BA /* Pods-APIAiMacOSSwiftDemo.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APIAiMacOSSwiftDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.mobilebloke.chatbot; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + A1C11CF21E1B2CC400D7E943 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E8DC645F30E438A1D49FDED9 /* Pods-APIAiMacOSSwiftDemo.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APIAiMacOSSwiftDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.mobilebloke.chatbot; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + A1C11CF41E1B2CC400D7E943 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F2EA4C0D804749B1565D745C /* Pods-APIAiMacOSSwiftDemoTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APIAiMacOSSwiftDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.mobilebloke.apiai.APIAiMacOSSwiftDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/APIAiMacOSSwiftDemo.app/Contents/MacOS/APIAiMacOSSwiftDemo"; + }; + name = Debug; + }; + A1C11CF51E1B2CC400D7E943 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5759CB0930E097F0EEF996BB /* Pods-APIAiMacOSSwiftDemoTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APIAiMacOSSwiftDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.mobilebloke.apiai.APIAiMacOSSwiftDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/APIAiMacOSSwiftDemo.app/Contents/MacOS/APIAiMacOSSwiftDemo"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A1C11CD11E1B2CC400D7E943 /* Build configuration list for PBXProject "APIAiMacOSSwiftDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1C11CEE1E1B2CC400D7E943 /* Debug */, + A1C11CEF1E1B2CC400D7E943 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1C11CF01E1B2CC400D7E943 /* Build configuration list for PBXNativeTarget "APIAiMacOSSwiftDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1C11CF11E1B2CC400D7E943 /* Debug */, + A1C11CF21E1B2CC400D7E943 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1C11CF31E1B2CC400D7E943 /* Build configuration list for PBXNativeTarget "APIAiMacOSSwiftDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1C11CF41E1B2CC400D7E943 /* Debug */, + A1C11CF51E1B2CC400D7E943 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A1C11CCE1E1B2CC400D7E943 /* Project object */; +} diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/AppDelegate.swift b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/AppDelegate.swift new file mode 100644 index 0000000..5547c13 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/AppDelegate.swift @@ -0,0 +1,31 @@ +// +// AppDelegate.swift +// APIAiMacOSSwiftDemo +// +// Created by Grant Kemp on 03/01/2017. +// Copyright © 2017 Grant Kemp. All rights reserved. +// + +import Cocoa +import ApiAI + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + let clientkey_APIAi = "b316a120a0ab4383980746032c21c4f5" + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + let configuration:AIConfiguration = AIDefaultConfiguration() + configuration.clientAccessToken = self.clientkey_APIAi + ApiAI.shared().configuration = configuration + + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + +} + diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Base.lproj/Main.storyboard b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..c522825 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Base.lproj/Main.storyboard @@ -0,0 +1,742 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Info.plist b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Info.plist new file mode 100644 index 0000000..89405a4 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2017 Grant Kemp. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/ViewController.swift b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/ViewController.swift new file mode 100644 index 0000000..96b0c18 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo/ViewController.swift @@ -0,0 +1,57 @@ +// +// ViewController.swift +// APIAiMacOSSwiftDemo +// +// Created by Grant Kemp on 03/01/2017. +// Copyright © 2017 Grant Kemp. All rights reserved. +// + +import Cocoa +import ApiAI + +class ViewController: NSViewController { + + @IBOutlet weak var obtn_StartListening: NSButton! + @IBOutlet weak var tf_outputTextBox: NSTextField! + + //Api AI + var request: AIVoiceRequest! + + // This is the method that takes the response from Api ai and shows it up in the text field and as an alert. + + @IBAction func abtn_StartListening(_ sender: NSButton) { + self.obtn_StartListening.isEnabled = false + self.request = ApiAI.shared().voiceRequest() + + + + request.setCompletionBlockSuccess({ (success, id) in + self.obtn_StartListening.isEnabled = true + let infoText = NSString.localizedStringWithFormat("%@", id as! CVarArg) + + self.showResponse(infoText: infoText) + }) { (request, error) in + self.obtn_StartListening.isEnabled = true + } + ApiAI.shared().enqueue(request) + + } + + + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + func showResponse(infoText:NSString) { + let alert = NSAlert() + alert.informativeText = infoText as String + tf_outputTextBox.stringValue = infoText as String + alert.alertStyle = .informational + alert.runModal() + + } +} + diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/APIAiMacOSSwiftDemoTests.swift b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/APIAiMacOSSwiftDemoTests.swift new file mode 100644 index 0000000..3560e95 --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/APIAiMacOSSwiftDemoTests.swift @@ -0,0 +1,36 @@ +// +// APIAiMacOSSwiftDemoTests.swift +// APIAiMacOSSwiftDemoTests +// +// Created by Grant Kemp on 03/01/2017. +// Copyright © 2017 Grant Kemp. All rights reserved. +// + +import XCTest +@testable import APIAiMacOSSwiftDemo + +class APIAiMacOSSwiftDemoTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/Info.plist b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/Info.plist new file mode 100644 index 0000000..6c6c23c --- /dev/null +++ b/ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemoTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/ApiAIMacOSDemoSwift/Podfile b/ApiAIMacOSDemoSwift/Podfile new file mode 100644 index 0000000..4cf42f2 --- /dev/null +++ b/ApiAIMacOSDemoSwift/Podfile @@ -0,0 +1,19 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'APIAiMacOSSwiftDemo' do + # Comment the next line if you're not using Swift and don't want to use dynamic frameworks + use_frameworks! + + # Pods for APIAiMacOSSwiftDemo + pod 'ApiAI/Core' + pod 'ApiAI/VoiceRequest' + pod 'ApiAI/ResponseMapping' + pod 'ApiAI/VoiceFileRequest' + + target 'APIAiMacOSSwiftDemoTests' do + inherit! :search_paths + # Pods for testing + end + +end From 9604f1b49d73512baabf38134801dc6919e7525f Mon Sep 17 00:00:00 2001 From: Grant Kemp Date: Tue, 10 Jan 2017 16:02:30 +0000 Subject: [PATCH 12/13] admin: added Travis build details --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index adf1b75..ee6ebdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,12 @@ script: #xcodebuild -workspace ApiAIDemoWatchOS/ApiAIDemoWatchOS.xcworkspace clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO - pod install --project-directory=./ApiAIMacOSDemo - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build + - pod install --project-directory=./ApiAIMacOSDemo + - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build + - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build + - pod install --project-directory=./ApiAIMacOSDemoSwift + - xcodebuild -workspace ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcworkspace -scheme ApiAIMacOSDemoSwift -sdk macosx build + notifications: email: recipients: From ebbdfb5f3a880b34466a58e336a4f7e96a622f5e Mon Sep 17 00:00:00 2001 From: Grant Kemp Date: Tue, 10 Jan 2017 16:33:30 +0000 Subject: [PATCH 13/13] bugfix: Tidy travis CI Build --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ee6ebdf..0e703a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,9 +19,8 @@ script: - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build - pod install --project-directory=./ApiAIMacOSDemo - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build - - xcodebuild -workspace ApiAIMacOSDemo/ApiAIMacOSDemo.xcworkspace -scheme ApiAIMacOSDemo -sdk macosx build - pod install --project-directory=./ApiAIMacOSDemoSwift - - xcodebuild -workspace ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcworkspace -scheme ApiAIMacOSDemoSwift -sdk macosx build + - xcodebuild -workspace ApiAIMacOSDemoSwift/APIAiMacOSSwiftDemo.xcworkspace -scheme APIAiMacOSSwiftDemo -sdk macosx build notifications: email: