I'm trying to save my VPN configuration to the preferences, which already works (I'm able to connect to my VPN). But for some reason each time i run the code again instead of using the last configuration it creates a new one. So, i end up with a bunch of configurations.
Here is my current code, if anyone could let me know what's going wrong with it that would be awesome. Thanks!
// Initialize Manager
NETunnelProviderManager *manager = [[NETunnelProviderManager alloc] init];
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Load Error: %#", error.description);
} else {
// Create the protocol object
NETunnelProviderProtocol *protocol = [[NETunnelProviderProtocol alloc] init]; // Create the protocol object
// Configure the protocol object
protocol.providerBundleIdentifier = #"com.nfisc.testvpn.ptp"; // Bundle ID of tunnel provider
protocol.providerConfiguration = #{}; // Currently blank, but will be used later
protocol.serverAddress = #"0.0.0.0"; // Ommited for security reasons
protocol.username = #"username"; // The username for the configuration
protocol.identityDataPassword = #"password"; // The password for the configuration
protocol.disconnectOnSleep = NO;
// Configure the manager with the protocol
manager.protocolConfiguration = protocol;
manager.enabled = true;
[manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Save Error: %#", error.description);
} else {
if ([[manager connection] status] != NEVPNStatusConnected) {
NSLog(#"Starting VPN");
[self start:manager];
} else {
NSLog(#"VPN Already Connected");
[_statusLabel setText:#"Connected"];
[_statusLabel setTextColor:[UIColor greenColor]];
}
}
}];
}
}];
Use + (void)loadAllFromPreferencesWithCompletionHandler:(void (^)(NSArray<NEAppProxyProviderManager *> *managers, NSError *error))completionHandler API instead.
create new protocol only when managers.count == 0 in the block.
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
if (error) {
NSLog(#"Load Error: %#", error.description);
}
NETunnelProviderManager *manager;
if (managers.count > 0) {
manager = managers[0];
}else {
manager = [[NETunnelProviderManager alloc] init];
manager.protocolConfiguration = [[NETunnelProviderProtocol alloc] init];
}
//... your code here...
}];
The solution was to call [NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler: first and then do the rest.
Fixed Code:
__block NETunnelProviderManager *manager = [[NETunnelProviderManager alloc] init];
NETunnelProviderProtocol *protocol = [[NETunnelProviderProtocol alloc] init];
protocol.providerBundleIdentifier = #"com.nfisc.testvpn.ptp"; // bundle ID of tunnel provider
protocol.providerConfiguration = #{#"key": #"value"};
protocol.serverAddress = #"0.0.0.0"; // VPN server address
protocol.username = #"username";
protocol.identityDataPassword = #"password";
manager.protocolConfiguration = protocol;
manager.enabled = true;
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
if ([managers count] > 0) {
manager = [managers objectAtIndex:0];
[self start:manager];
} else {
[manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error 1: %#", error.description);
} else {
[manager loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(#"Error 2: %#", error.description);
} else {
[self start:manager];
}
}];
}
}];
}
}
Related
I'm trying to set up customized vpn tunnel
- (void) openTunnel{
[vpnManager loadFromPreferencesWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"%#", error);
}else{
NSError *startError = nil;
[self->vpnManager.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
if(startError != nil){
NSLog(#"viewcontroller: startError: %#", startError);
}else{
NSLog(#"Complete");
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:NEVPNStatusDidChangeNotification
object:nil];
}
}
}];}
startVPNTunnelWithOptions starts a customized tunnel as following
- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(NSError *error))completion{
NSLog(#"===> ");
NSError *error = nil;
vpnAdapter = [[OpenAdapter alloc] init];
vpnAdapter.delegate = self;
// get config
config = [[NSDictionary alloc] init];
NETunnelProviderProtocol *protocol = (NETunnelProviderProtocol *)self.protocolConfiguration;
config = protocol.providerConfiguration;
host = config[#"server"];
// Load config data
username = config[#"username"];
password = config[#"password"];
option = config[#"option"];
NSError *newError = [NSError errorWithDomain:VPNTunnelProviderErrorDomain
code:TunnelProviderErrorCodeInvalidConfiguration
userInfo:#{NSLocalizedDescriptionKey: #"Settings validation failed!"}];
if(option != nil){
[vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(int success) {
if(success == 0)
{NSLog(#"packettunnel: newerror: %d", 0);
completion(error);}
else {
NSLog(#"packettunnel: newerror: %#", newError);
completion(newError);
}
}];
}else{
[vpnAdapter connect:host user:username pass:password add:NO completionHandler:^(int success) {
if(success == 0){
{NSLog(#"packettunnel: newerror: %d", 0);
completion(error);}
else
{
NSLog(#"packettunnel: newerror: %#", newError);
completion(newError);
}
}];
}
}
when testing with fake credentials(works fine with correct one), it supposed to print startError, but it doesn't. I can confirm that startTunnelWithOptions it actually returns newError from NSLog, but somehow, startVPNTunnelWithOptions doesn't return any error.
anyone could help?
thanks
I can't seem to find the code to send my token to my firebase backend.
- (void)addCardViewController:(STPAddCardViewController *)addCardViewController didCreateToken:(STPToken *)token completion:(STPErrorBlock)completion {
[self submitTokenToBackend:token completion:^(NSError *error) {
if (error) {
completion(error);
} else {
[self dismissViewControllerAnimated:YES completion:^{
[self showReceiptPage];
}];
}
}];
}
Try this code,
STPAddress *address = [[STPAddress alloc] init];
address.name ="Test";
address.line1 = #"Test Address-1";
address.line2 = #"Test Address-2";
address.city = #"City";
address.postalCode = #"1234";
address.state = #"State";
address.country = #"Country";
STPCard *stripCard;
stripCard = [[STPCard alloc] init];
stripCard.number = strCard_Number;
stripCard.cvc = strCard_Cvv;
stripCard.expMonth = month;
stripCard.expYear = year;
stripCard.address = address;
stripCard.currency = #"INR";
[[STPAPIClient sharedClient] createTokenWithCard:stripCard completion:^(STPToken * _Nullable token, NSError * _Nullable error)
{
NSString *strMess= #"";
if(error) {
strMess = [error localizedDescription];
}
else {
strMess = stringValue(token.tokenId);
strMess = [NSString stringWithFormat:#"Token:\n-------\n%#\n\n\nCard Details:\n-------\n%#",strMess,token.allResponseFields];
//[Function showAlertMessage:strMess autoHide:NO];
NSString *strToken = #"";
strToken = token.tokenId;
NSLog(#"strToken: %#",strToken);
}
NSLog(#"strMess: %#",strMess);
}];
I am implementing MailCore2 to fetch user's email in my app. I have successfully fetched the email of the user, code is as follows : -
- (void)loadAccountWithUsername:(NSString *)username
password:(NSString *)password
hostname:(NSString *)hostname
oauth2Token:(NSString *)oauth2Token
{
self.imapSession = [[MCOIMAPSession alloc] init];
self.imapSession.hostname = hostname;
self.imapSession.port = 993;
self.imapSession.username = username;
self.imapSession.password = password;
if (oauth2Token != nil) {
self.imapSession.OAuth2Token = oauth2Token;
self.imapSession.authType = MCOAuthTypeXOAuth2;
}
self.imapSession.connectionType = MCOConnectionTypeTLS;
MasterViewController * __weak weakSelf = self;
self.imapSession.connectionLogger = ^(void * connectionID, MCOConnectionLogType type, NSData * data) {
#synchronized(weakSelf) {
if (type != MCOConnectionLogTypeSentPrivate) {
// NSLog(#"event logged:%p %i withData: %#", connectionID, type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
}
};
// Reset the inbox
self.messages = nil;
self.totalNumberOfInboxMessages = -1;
self.isLoading = NO;
self.messagePreviews = [NSMutableDictionary dictionary];
[self.tableView reloadData];
NSLog(#"checking account");
self.imapCheckOp = [self.imapSession checkAccountOperation];
[self.imapCheckOp start:^(NSError *error) {
MasterViewController *strongSelf = weakSelf;
NSLog(#"finished checking account.");
if (error == nil) {
[strongSelf loadLastNMessages:NUMBER_OF_MESSAGES_TO_LOAD];
} else {
NSLog(#"error loading account: %#", error);
}
strongSelf.imapCheckOp = nil;
}];
}
- (void)loadLastNMessages:(NSUInteger)nMessages
{
self.isLoading = YES;
MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind)
(MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |
MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |
MCOIMAPMessagesRequestKindFlags);
NSString *inboxFolder = #"INBOX";
MCOIMAPFolderInfoOperation *inboxFolderInfo = [self.imapSession folderInfoOperation:inboxFolder];
[inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info)
{
BOOL totalNumberOfMessagesDidChange =
self.totalNumberOfInboxMessages != [info messageCount];
self.totalNumberOfInboxMessages = [info messageCount];
NSUInteger numberOfMessagesToLoad =
MIN(self.totalNumberOfInboxMessages, nMessages);
if (numberOfMessagesToLoad == 0)
{
self.isLoading = NO;
return;
}
MCORange fetchRange;
// If total number of messages did not change since last fetch,
// assume nothing was deleted since our last fetch and just
// fetch what we don't have
if (!totalNumberOfMessagesDidChange && self.messages.count)
{
numberOfMessagesToLoad -= self.messages.count;
fetchRange =
MCORangeMake(self.totalNumberOfInboxMessages -
self.messages.count -
(numberOfMessagesToLoad - 1),
(numberOfMessagesToLoad - 1));
}
// Else just fetch the last N messages
else
{
fetchRange =
MCORangeMake(self.totalNumberOfInboxMessages -
(numberOfMessagesToLoad - 1),
(numberOfMessagesToLoad - 1));
}
self.imapMessagesFetchOp =
[self.imapSession fetchMessagesByNumberOperationWithFolder:inboxFolder
requestKind:requestKind
numbers:
[MCOIndexSet indexSetWithRange:fetchRange]];
[self.imapMessagesFetchOp setProgress:^(unsigned int progress) {
NSLog(#"Progress: %u of %u", progress, numberOfMessagesToLoad);
}];
__weak MasterViewController *weakSelf = self;
[self.imapMessagesFetchOp start:
^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages)
{
MasterViewController *strongSelf = weakSelf;
NSLog(#"fetched all messages.");
self.isLoading = NO;
NSSortDescriptor *sort =
[NSSortDescriptor sortDescriptorWithKey:#"header.date" ascending:NO];
NSMutableArray *combinedMessages =
[NSMutableArray arrayWithArray:messages];
[combinedMessages addObjectsFromArray:strongSelf.messages];
strongSelf.messages =
[combinedMessages sortedArrayUsingDescriptors:#[sort]];
[strongSelf.tableView reloadData];
}];
}];
}
Now I want to integrate search email functionality in my app. Is there any method available in mailcore2 framework to fetch the searched email with keyword.
Already tried with the link but it was not helpful.
iOS-Is there any method available for fetching CTCoreMessage with specific key words from CTCoreAccount or CTCoreFolder in Mailcore library?
I create a subscription for create and update. Creation always works perfect and I get push notifications from other devices. Update goes to iCloud, you can see them there, but push notifications are not delivered to the device.
- (void)subscribeWithType:(NSString*)type completionHandler:(void(^)(CKSubscription *))completionHandler
{
if (self.enabled == NO || _available == NO || _reachability.currentReachabilityStatus != ReachableViaWiFi)
{
if (completionHandler)
{
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(nil);
});
}
return;
}
NSPredicate *truePredicate = [NSPredicate predicateWithValue:YES];
CKSubscriptionOptions options = CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordUpdate;
CKSubscription *subscription = [[CKSubscription alloc] initWithRecordType:type
predicate:truePredicate
subscriptionID:[CTUtils GetUUID]
options:options];
CKNotificationInfo *notification = [[CKNotificationInfo alloc] init];
notification.shouldSendContentAvailable = YES;
notification.alertLocalizationKey = #"";
notification.shouldBadge = NO;
subscription.notificationInfo = notification;
CKModifySubscriptionsOperation *operation = [[CKModifySubscriptionsOperation alloc] initWithSubscriptionsToSave:#[subscription] subscriptionIDsToDelete:nil];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block CKSubscription *resultSubscription = nil;
operation.modifySubscriptionsCompletionBlock = ^(NSArray *savedSubscriptions, NSArray *deletedSubscriptionIDs, NSError *operationError) {
if (operationError)
{
if (iCloudLog)
{
NSLog(#"create %# subscriptions error : %#", type, operationError);
}
}
else
{
resultSubscription = savedSubscriptions.firstObject;
if (iCloudLog)
{
NSLog(#"created subscription for %#: %#", type, savedSubscriptions);
}
}
dispatch_semaphore_signal(semapthore);
};
dispatch_async(dispatch_get_main_queue(), ^{
[self.privateDatabase addOperation:operation];
});
dispatch_time_t time = DISPATCH_TIME_FOREVER;
dispatch_semaphore_wait(semapthore, time);
if (completionHandler)
{
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(resultSubscription);
});
}
}
Anybody see here error or why not implemented push notification to update?
Has anyone found the replacement for
[GKAchievement reportAchievementWithCompletionHandler]?
Typically when things are deprecated the docs indicate a replacement. Not so with this one so far and I wanted to cross this off the list of possible causes of another issue we are seeing.
Was looking for the same info and saw your post, here is what I went with after not finding anything either:
NSArray *achievements = [NSArray arrayWithObjects:achievement, nil];
[GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"Error in reporting achievements: %#", error);
}
}];
Here is apple's full code (same/similar to Silly Goose's Answer)
- (void) completeMultipleAchievements
{
GKAchievement *achievement1 = [[GKAchievement alloc] initWithIdentifier: #"DefeatedFinalBoss"];
GKAchievement *achievement2 = [[GKAchievement alloc] initWithIdentifier: #"FinishedTheGame"];
GKAchievement *achievement3 = [[GKAchievement alloc] initWithIdentifier: #"PlayerIsAwesome"];
achievement1.percentComplete = 100.0;
achievement2.percentComplete = 100.0;
achievement3.percentComplete = 100.0;
NSArray *achievementsToComplete = [NSArray arrayWithObjects:achievement1,achievement2,achievement3, nil];
[GKAchievement reportAchievements: achievementsToComplete withCompletionHandler:^(NSError *error)
{
if (error != nil)
{
NSLog(#"Error in reporting achievements: %#", error);
}
}];
}
This works in iOS7 with no issues.
- (void)checkAchievements
{
if(myScore >= 25000){
GKAchievement *achievement= [[GKAchievement alloc] initWithIdentifier:#"Achiev1"];
achievement.percentComplete = 100.0;
achievement.showsCompletionBanner = YES;
[self Achievements:achievement];
}
}
-(void)Achievements:(GKAchievement*)achievement {
NSArray *achievements = [NSArray arrayWithObjects:achievement, nil];
[GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"Error in reporting achievements: %#", error);
}
}];
}