Open app from App Store not the same as in board - ios

I have a 'Terms and Conditions' controller I represent in the first launch of the app, but when opening the app in the first time from the App Store page the Terms and Conditions' controller not shown- only after I close the app and reopen it from the device itself (not the App Store page) then the controller is shown.
this code is from the launched screen controller:
- (void)viewDidLoad {
[self agreedToServerTerms];
}
- (void)agreedToServerTerms {
[[HttpUtils instance] httpRequest:TERMS_AGREEMENT_URL :params completionHandler:^(NSData *data, NSError *error) {
#try {
bool acceptTerms = false;
if (error) {
[Utils log:[NSString stringWithFormat:#"agreedToServerTerms error=%#", error]];
} else {
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!error) {
acceptTerms = [jsonData.allValues[0] boolValue];
if (!acceptTerms) {
TermsAndConditionController *tac = [[TermsAndConditionController alloc] initWithNibName:#"TermsAndConditionController" bundle:nil];
tac.delegate = self;
[[SlideNavigationController sharedInstance] pushViewController:tac animated:false];
}
else {
[self performSelectorInBackground:#selector(initialApp) withObject:nil];
}
} else {
[Utils log:[NSString stringWithFormat:#"parsing jsonData error = %#" ,error]];
}
}
} #catch (NSException *e) {
[Utils log:[NSString stringWithFormat:#"Exception occurred: %#, %#", e, [e userInfo]]];
}
}];
}
from App delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
LaunchScreenController *bbp = [[LaunchScreenController alloc] initWithNibName:#"LaunchScreenController" bundle:nil];
[[SlideNavigationController sharedInstance] pushViewController:bbp animated:YES];
if (_launchedURL) {
bbp.launchedURL = _launchedURL;
}
[self.window addSubview:bbp.view];
}

herewith how I do almost the exact same thing. I think you need to rework yours, it could be a bit different, but this may help.
In the first VC that my app displays, in its viewWillAppear message, I have the following code
// Terms of use
if ( [NSUserDefaults.standardUserDefaults integerForKey:#"tou"] != 20170614 )
{
[self performSegueWithIdentifier:#"tou" sender:nil];
[NSUserDefaults.standardUserDefaults setInteger:20170614 forKey:#"tou"];
}
This uses user defaults to note if the terms of use have ever been presented and, if so, it marks #"tou" with some arbitrary value. In your case you can set the logic in your controller and only mark it once the user accepts.
This requires a segue in the storyboard called #"tou" that will present your T&C controller and you may need to prevent exit if the user does not agree, but the idea is to segue away from your first VC if the user did not agree yet to present the user with the T&C rather than injecting it into the app delegate as you do at present.

Related

Set text in Active Conversation in iMessage

I wrote some code to add text to the Messages.app input field in my iMessage extension.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"didSelect called");
NSLog(#"%d", 1);
[[self activeConversation] insertText:#"https://google.com" completionHandler:^(NSError * error) {
NSLog(#"Error happened");
NSLog(#"Error: %#", error);
}];
NSLog(#"%d", 2);
}
The strange part is that all of the normal logs are happening. The app will log "didSelect called", "1" and "2". However, the message - the Google url - isn't being inserted, and the error logs aren't being shown. So I don't really have a clue as to what's going wrong. Any idea's what I'm doing wrong?
Solution #1
Send correct reference from MessagesViewController to your view controller.
Check activeConversation value for nil:
if ([self activeConversation] != nil) {
[[self activeConversation] insertText:#"Some text" completionHandler:^(NSError * _Nullable error) {
NSLog(#"error: %#", error.localizedDescription);
}];
} else {
NSLog(#"Conversation is nil");
}
Solution #2
Create Singleton in iMessage extension name space.
In MessagesViewController in - (void)viewDidLoad setup reference to
your MSConversation: [[Conversation shared] activeConversation] = [self activeConversation];
Use [[Conversation shared] activeConversation] insertText: .... ];
for sending messages from any controllers.

WatchKit App Connectivity Issues

I'm trying to make a simple watch app that displays information sent by the companion app. I'm having some trouble getting the WatchKit app to properly receive the information.
On the sender side I have the following code:
- (void)viewDidLoad {
[super viewDidLoad];
// Prevents UIWebView from displaying under nav bar
self.navigationController.navigationBar.translucent = NO;
_timer = [NSTimer scheduledTimerWithTimeInterval:12.0 target:self selector:#selector(showAlert) userInfo:nil repeats:NO];
_diningLocations = [[NSMutableArray alloc] initWithCapacity:0];
if ([WCSession isSupported]) {
self.session = [WCSession defaultSession];
self.session.delegate = self;
[self.session activateSession];
// The following line works
//[self.session updateApplicationContext:#{#"hello" : #"world"} error:nil];
}
- (void)grabLocationsFromServer {
_query = [PFQuery queryWithClassName:self.tableName];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[_query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// Do stuff
[self.locationTable reloadData];
[self loadWatchApp];
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
}];
}
- (void)loadWatchApp {
if(self.session) {
if (self.session.paired && self.session.watchAppInstalled) {
NSError *error;
[self.session updateApplicationContext:#{#"Locations": self.diningLocations} error:&error];
}
}
}
On the receiving end I have this simple code snippet:
func loadTableData(data: [RFDiningLocation]) {
table.setNumberOfRows(data.count, withRowType: "location")
for i in 0..<data.count {
let row = table.rowControllerAtIndex(i) as! RFDiningRowController
// row.label.setText(data[i].name)
row.label.setText("Hello, world!")
}
}
When I call updateApplicationContext in viewDidLoad, it works 100% fine, but when I call it from within another function the WatchKit app just doesn't respond. I can confirm that loadWatchApp is called as well as updateApplicationContext. Thanks!
I would implement the session function from WCSessionDelegate activationDidCompleteWithState and then in the callback if state is activated then call your grabLocationsFromServer function. If grabLocationsFromServer gets called before you activate the Watch session, that could be why your application context isn't being updated.
Also, it's suggested that you call activate session as soon as possible, such as in the init of the App Delegate.
I was just experimenting before you said this worked for you, so here's what I'm seeing:
On startup of watch (initial connection), there is a call to activationDidCompleteWithState but there is no context yet, so didReceiveApplicationContext is not called.
Watch app updates per expected applicationContext only occurs when I send an empty message in sessionReachabilityDidChange. My understanding is that I have to "awake" the phone app in the background by sending this initial message. This message can be ignored on the phone side.
func sessionReachabilityDidChange(session: WCSession) {
if session.reachable {
sendMessage(["InitialMessage": true], replyHandler: nil, errorHandler: nil)
}
}

SKStoreProductViewControllerDelegate method not being called

I'm simply trying to implement the iTunes store screen in my application, and it displays correctly. However, when the user is finished with the screen (makes a purchase or clicks 'cancel') all I get is a white screen, and I have to completely close my app and reopen it.
It turns out my productViewControllerDidFinish method isn't being called.
I have a table view controller that has the SKStoreProductViewControllerDelegate and I'm presenting and dismissing the store view in the same class, so why isn't the delegate method being called?
- (void)toStore:(Button*)sender {
SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];
[storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #"stuff"} completionBlock:^(BOOL result, NSError *error) {
if (error) {
NSLog(#"Error %# with User Info %#.", error, [error userInfo]);
} else {
[self presentViewController:storeProductViewController animated:YES completion:nil];
}
}];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController*)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
Both in a UITableViewController. Thanks in advance!
Set delegate of SKStoreProductViewController controller.. You missed to do that..
Set it just below object allocation..
storeProductViewController.delegate = self;

Spotify EXC_BAD_EXE while second time tap on Login Button after dismiss LoginViewController

Hi i Intigrate SpotifyLib CocoaLibSpotify iOS Library 17-20-26-630 into my Project. I open its SPLoginViewController using Bellow Method:-
-(void)OpenSpotify
{
NSError *error = nil;
[SPSession initializeSharedSessionWithApplicationKey:[NSData dataWithBytes:&g_appkey length:g_appkey_size]
userAgent:#"com.mycomp.spotify"
loadingPolicy:SPAsyncLoadingImmediate
error:&error];
if (error != nil) {
NSLog(#"CocoaLibSpotify init failed: %#", error);
abort();
}
[[SPSession sharedSession] setDelegate:self];
[self performSelector:#selector(showLogin) withObject:nil afterDelay:0.0];
}
-(void)showLogin
{
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
controller.allowsCancel = YES;
//controller.view.frame=;
[self presentViewController:controller animated:YES completion:nil];
}
At First time that Appear Spotify Login Screen. After that I tap On Cancel Button, and Try to open again login screen then i got crash EXC_BAD_EXE at this line. sp_error createErrorCode = sp_session_create(&config, &_session);
UPDATE
I Found exet where is got BAD_EXC
in this method
+(void)dispatchToLibSpotifyThread:(dispatch_block_t)block waitUntilDone:(BOOL)wait {
NSLock *waitingLock = nil;
if (wait) waitingLock = [NSLock new];
// Make sure we only queue one thing at a time, and only
// when the runloop is ready for it.
[runloopReadyLock lockWhenCondition:1];
CFRunLoopPerformBlock(libspotify_runloop, kCFRunLoopDefaultMode, ^() {
[waitingLock lock];
if (block) { #autoreleasepool { block(); } }
[waitingLock unlock];
});
if (CFRunLoopIsWaiting(libspotify_runloop)) {
CFRunLoopSourceSignal(libspotify_runloop_source);
CFRunLoopWakeUp(libspotify_runloop);
}
[runloopReadyLock unlock]; // at hear when my debug poin reach after pass this i got bad_exc
if (wait) {
[waitingLock lock];
[waitingLock unlock];
}
}
after doing lots of search i got Solution i check that whether the session already exists then i put if condition like:-
-(void)OpenSpotify
{
SPSession *session = [SPSession sharedSession];
if (!session) {
NSError *error = nil;
[SPSession initializeSharedSessionWithApplicationKey:[NSData dataWithBytes:&g_appkey length:g_appkey_size]
userAgent:#"com.mycomp.spotify"
loadingPolicy:SPAsyncLoadingImmediate
error:&error];
if (error != nil) {
NSLog(#"CocoaLibSpotify init failed: %#", error);
abort();
}
[[SPSession sharedSession] setDelegate:self];
}
[self performSelector:#selector(showLogin) withObject:nil afterDelay:0.0];
}
-(void)showLogin
{
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
controller.allowsCancel = YES;
[self presentViewController:controller animated:YES completion:nil];
}
Now no crash and working fine.

Getting Twitter to display the option of going to my settings page if Twitter is not set up? iOS5+

If I access Twitter, I would prefer to use the automatic alert box asking that the user go to settings, yet can't get it to work and provide my own default dialog, which I really don't want to do.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"indexPath.row %i", indexPath.row);
if (indexPath.row == 0) {
store = [[ACAccountStore alloc] init]; // Long-lived
twitterType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[store requestAccessToAccountsWithType:twitterType withCompletionHandler:^(BOOL granted, NSError *error) {
if (granted) {
// Access has been granted, now we can access the accounts
twitterAccounts = [store accountsWithAccountType:twitterType];
if (twitterAccounts.count == 1) {
[self getTwitterData:[twitterAccounts objectAtIndex:0]];
} else {
[self selectTwitterAccount];
}
} else {
// Prefer NOT to do this ************************************
[self performSelectorOnMainThread:#selector(showTwitterError) withObject:nil waitUntilDone:NO];
}
}];
}
It is little tricky , i get by the removing the subviews in *TWTWeetComposeViewController*, so it shows only alert when user is not loged in and by the clicking on setting button , we can open the setting page in my app.
+ (void)setAlertForSettingPage :(id)delegate
{
// Set up the built-in twitter composition view controller.
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
// Create the completion handler block.
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
[delegate dismissModalViewControllerAnimated:YES];
}];
// Present the tweet composition view controller modally.
[delegate presentModalViewController:tweetViewController animated:YES];
//tweetViewController.view.hidden = YES;
for (UIView *view in tweetViewController.view.subviews){
[view removeFromSuperview];
}
}
Here, delegate is your viewcontroller, if you are using this method inside your viewcontroller just use self instead of delegate.
I had to face the same problem and found this sollution
To my knowledge this was only possible in iOS versions 5.0 - 5.0.1.
It was then depreciated again in iOS 5.1
So NO solution at the moment...
In case you would like to use the iOS 5 part:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs://"]];
And some more reading on the same topic

Resources