StoreKit delegate method not getting called - objective-c

I have a problem. SKProductsRequest delegate methods are never getting called. this was previously asked but it had no answers. StoreKit delegate functions are not getting called
I'm not native english speaker, I may sound funny at times :P :(
I want to implement StoreKit in my iOS app. I made a class to handle all the StoreKit communication. This is the code:
#implementation VRStoreController
- (void) requestProducts
{
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers:
[NSSet setWithObject: #"myProductID"]];
request.delegate = self;
[request start];
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
}
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"F7U12");
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSArray *myProducts = response.products;
NSLog(#"%#", myProducts);
}
I created an instance in my app delegate
#interface VRAppDelegate
#property (strong, nonatomic) VRStoreController *store;
#end
Strangely, this code works ok when I run [store requestProducts] in my appDidFinishLaunching: method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//app initialization...
self.store = [[VRStoreController alloc]init];
[store requestProducts]; //This works ok, delegate method gets called.
return YES;
}
But when I run the code in settings tableView:didSelectRowAtIndexPath: the delegate method never gets called.
//VRAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//app initialization...
self.store = [[VRStoreController alloc]init];//initialize store
return YES;
}
//VRSettingsViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
//case 0, 1...
case 2:
{
VRStoreController *store = ((VRAppDelegate *)[UIApplication sharedApplication].delegate).store;
[store requestProducts]; //calls SKProductRequest start, but never calls delegate method.
NSLog(#"GO PRO");
}
default:
break;
}
}
I don't know what am I doing bad. Tried almost everything and no errors, no crashes, but the delegate never gets called. Any help would be very appreciated.
Thanks so much in advance!

The SKProductsRequestDelegate protocol also conforms to the SKRequestDelegate protocol, which has the following methods:
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error;
- (void)requestDidFinish:(SKRequest *)request;
Implement those and see if either of them is being called. You're probably getting an error or otherwise unexpected response.

I finally found the problem I had.
I was not retaining the SKProductRequest, so the request was started and then it was dumped.
I fixed it by doing this
//VRStoreController.m
#interface VRStoreController ()
#property (strong, nonatomic) SKProductRequest *request; //Store the request as a property
#end
#implementation VRStoreController
#synthesize request;
- (void) requestProducts
{
self.request = [[SKProductsRequest alloc] //save the request in the property
initWithProductIdentifiers:
[NSSet setWithObject: #"myProductID"]];
self.request.delegate = self;
[self.request start];
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
}
Although the problem is fixed, I think that there should't be the need of retaining request, as I already called the start method and have set its delegate, it should do everything else by its own, and should retain itself until it receives response (or error) and after that deallocate itself.

Related

Swift 3 - superclass method is executing instead of its override counterpart

How can I override the ObjC methods, runThisMethod and controller:didChangeObject:, from the ViewControllerA class so that the app executes the counterparts from the Swift subclass, ViewControllerC, instead? In the code below, [ViewControllerA runThisMethod(someParameter)] will execute when the app detects a change in fetchedResultsController (via [ViewControllerA controller:didChangeObject:]. Can somebody help me see what I'm missing?
Main.swift
let vc = ViewControllerC.init()
self.myNavigationController?.pushViewController(vc, animated: true)
ViewControllerA.h
#interface ViewControllerA : UIViewController <NSFetchedResultsControllerDelegate>
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
- (void)setUpFetchedResultsController;
- (void)runThisMethod:(SomeParameterClass *)someParameter;
#end
ViewControllerA.m
#implementation ViewControllerA
- (void)setUpFetchedResultsController
{
// build fetch "request" here
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[[MYCoreDataManager sharedCoreDataManager] managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)someParameter atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
[self runThisMethod:someParameter]
}
- (void)runThisMethod:(SomeParameterClass *)someParameter
{
NSLog(#"This method will execute")
}
#end
ViewControllerB.h
#interface ViewControllerB : ViewControllerA
// declare a bunch of properties
#end
ViewControllerB.m
#implementation ViewControllerB
- (void)viewWillAppear:(BOOL)animated {
[self setUpFetchedResultsController];
}
#end
ViewControllerC.swift
class ViewControllerC: ViewControllerB {
override func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange someParameter: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
// this function won't run
self.runThisMethod(someParameter)
}
override func runThisMethod(someParameter){
// this function won't run
}
}
When I set up a sample project with the code as you've mentioned (and set up a bridging header file which imports in ViewControllerB.h) the overridden runThisMethod on ViewControllerC executes correctly. This is with Xcode 8.2.1. So everything appears to work as it should with the set up you mention.
Could you perhaps upload a sample project showing the behaviour that you mention so that we can take a look? My suspicion is that something is not set up correctly somewhere ...
One thing you might not be doing (since you've only provided part of the code) is overriding NSFetchedResultsController's didChangeObject delegate method in ViewControllerC.
Turns out the problem was in the predicate of my fetchedResultsController property. The predicate had a parameter that will causing fetchResultsController to always be nil when performing the fetch. Thus, the delegate method, controller:didChangeObject: was not being triggered.

Mac OSX Storyboard : communicate between NSViewController

I use storyboard in a OS X cocoa application project with a SplitView controller and 2 others view controller LeftViewController and RightViewController.
In the LeftViewController i have a tableView that display an array of name. The datasource and delegate of the tableview is the LeftViewController.
In the RightViewController i just have a centered label that display the select name. I want to display in the right view the name selected in the left view.
To configure the communication between the 2 views controllers i use the AppDelegate and i define 2 property for each controller in AppDelegate.h
The 2 property are initialized in the viewDidLoad of view controller using the NSInvocation bellow :
#implementation RightViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
id delg = [[NSApplication sharedApplication] delegate];
SEL sel1 = NSSelectorFromString(#"setRightViewController:");
NSMethodSignature * mySignature1 = [delg methodSignatureForSelector:sel1];
NSInvocation * myInvocation1 = [NSInvocation
invocationWithMethodSignature:mySignature1];
id me = self;
[myInvocation1 setTarget:delg];
[myInvocation1 setSelector:sel1];
[myInvocation1 setArgument:&me atIndex:2];
[myInvocation1 invoke];
}
I have the same in LeftViewController.
Then if i click on a name in the table view, i send a message to the delegate with the name in parameter and the delegate update the label of the RightViewController with the given name. It works fine but according to apple best practice it’s not good.
Is there another way to communicate between 2 view controller inside a storyboard ?
I've already read a lot of post but found nothing for OS X.
You can download the simple project here : http://we.tl/4rAl9HHIf1
This is more advanced topic of app architecture (how to pass data).
Dirty quick solution: post NSNotification together with forgotten representedObject:
All NSViewControllers have a nice property of type id called representedObject. This is one of the ways how to pass data onto NSViewController. Bind your label to this property. For this simple example we will set representedObject some NSString instance. You can use complex object structure as well. Someone can explain in comments why storyboards stopped to show representedObject (Type safety in swift?)
Next we add notification observer and set represented object in handler.
#implementation RightViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:#"SelectionDidChange" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
//[note object] contains our NSString instance
[self setRepresentedObject:[note object]];
}];
}
#end
Left view controller and its table:
Once selection changes we post a notification with our string.
#interface RightViewController () <NSTableViewDelegate, NSTableViewDataSource>
#end
#implementation RightViewController
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [[self names] count];
}
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row
{
return [self names][row];
}
- (NSArray<NSString *>*)names
{
return #[#"Cony", #"Brown", #"James", #"Mark", #"Kris"];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSTableView *tableView = [notification object];
NSInteger selectedRow = [tableView selectedRow];
if (selectedRow >= 0) {
NSString *name = [self names][selectedRow];
if (name) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"SelectionDidChange" object:name];
}
}
}
PS: don't forget to hook tableview datasource and delegate in storyboard
Why is this solution dirty? Because once your app grows you will end up in notification hell. Also view controller as data owner? I prefer window controller/appdelegate to be Model owner.
Result:
AppDelegate as Model owner.
Our left view controller will get it's data from AppDelegate. It is important that AppDelegate controls the data flow and sets the data (not the view controller asking AppDelegate it's table content cause you will end up in data synchronization mess). We can do this again using representedObject. Once it's set we reload our table (there are more advanced solutions like NSArrayController and bindings). Don't forget to hook tableView in storyboard. We also modify tableview's delegate methos the tableViewSelectionDidChange to modify our model object (AppDelegate.selectedName)
#import "LeftViewController.h"
#import "AppDelegate.h"
#interface LeftViewController () <NSTableViewDelegate, NSTableViewDataSource>
#property (weak) IBOutlet NSTableView *tableView;
#end
#implementation LeftViewController
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [[self representedObject] count];
}
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row
{
return [self representedObject][row];
}
- (void)setRepresentedObject:(id)representedObject
{
[super setRepresentedObject:representedObject];
//we need to reload table contents once
[[self tableView] reloadData];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSTableView *tableView = [notification object];
NSInteger selectedRow = [tableView selectedRow];
if (selectedRow >= 0) {
NSString *name = [self representedObject][selectedRow];
[(AppDelegate *)[NSApp delegate] setSelectedName:name];
} else {
[(AppDelegate *)[NSApp delegate] setSelectedName:nil];
}
}
In RightViewController we delete all code. Why? Cause we will use binding AppDelegate.selectedName <--> RightViewController.representedObject
#implementation RightViewController
#end
Finally AppDelegate. It needs to expose some properties. What is interesting is how do I get my hands on all my controllers? One way (best) is to instantiate our own window controller and remember it as property. The other way is to ask NSApp for it's windows (be careful here with multiwindow app). From there we just ask contentViewController and loop through childViewControllers. Once we have our controllers we just set/bind represented objects.
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (nonatomic) NSString *selectedName;
#property (nonatomic) NSMutableArray <NSString *>*names;
#end
#import "AppDelegate.h"
#import "RightViewController.h"
#import "LeftViewController.h"
#interface AppDelegate () {
}
#property (weak, nonatomic) RightViewController *rightSplitViewController;
#property (weak, nonatomic) LeftViewController *leftSplitViewController;
#property (strong, nonatomic) NSWindowController *windowController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_names = [#[#"Cony", #"Brown", #"James", #"Mark", #"Kris"] mutableCopy];
_selectedName = nil;
NSStoryboard *storyboard = [NSStoryboard storyboardWithName:#"Main"
bundle:[NSBundle mainBundle]];
NSWindowController *windowController = [storyboard instantiateControllerWithIdentifier:#"windowWC"];
[self setWindowController:windowController];
[[self windowController] showWindow:nil];
[[self leftSplitViewController] setRepresentedObject:[self names]];
[[self rightSplitViewController] bind:#"representedObject" toObject:self withKeyPath:#"selectedName" options:nil];
}
- (RightViewController *)rightSplitViewController
{
if (!_rightSplitViewController) {
NSArray<NSViewController *>*vcs = [[[self window] contentViewController] childViewControllers];
for (NSViewController *vc in vcs) {
if ([vc isKindOfClass:[RightViewController class]]) {
_rightSplitViewController = (RightViewController *)vc;
break;
}
}
}
return _rightSplitViewController;
}
- (LeftViewController *)leftSplitViewController
{
if (!_leftSplitViewController) {
NSArray<NSViewController *>*vcs = [[[self window] contentViewController] childViewControllers];
for (NSViewController *vc in vcs) {
if ([vc isKindOfClass:[LeftViewController class]]) {
_leftSplitViewController = (LeftViewController *)vc;
break;
}
}
}
return _leftSplitViewController;
}
- (NSWindow *)window
{
return [[self windowController] window];
}
//VALID SOLUTION IF YOU DON'T INSTANTIATE STORYBOARD
//- (NSWindow *)window
//{
// return [[NSApp windows] firstObject];
//}
#end
Result: works exactly the same
PS: If you instantiate own window Controller don't forget to delete initial controller from Storyboard
Why is this better? Cause all changes goes to model and models sends triggers to redraw views. Also you will end up in smaller view controllers.
What can be done more? NSObjectController is the best glue between your model objects and views. It also prevents retain cycle that sometimes can happen with bindings (more advanced topic). NSArrayController and so on...
Caveats: not a solution for XIBs
I managed to get what i want by adding the following code in AppDelegate.m :
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
//
NSStoryboard *storyboard = [NSStoryboard storyboardWithName:#"Main"
bundle:[NSBundle mainBundle]];
self.windowController = [storyboard instantiateControllerWithIdentifier:#"windowController"];
self.window = self.windowController.window;
self.splitViewController = (NSSplitViewController*)self.windowController.contentViewController;
NSSplitViewItem *item0 = [self.splitViewController.splitViewItems objectAtIndex:0];
NSSplitViewItem *item1 = [self.splitViewController.splitViewItems objectAtIndex:1];
self.leftViewController = (OMNLeftViewController*)item0.viewController;
self.rightViewController = (OMNRightViewController*)item1.viewController;
[self.window makeKeyAndOrderFront:self];
[self.windowController showWindow:nil];
}
We also need to edit the storyboard NSWindowController object as follow :
Uncheck the checkbox 'Is initial controller' because we add it programmatically in AppDelegate.m.
Now the left and right view can communicate. Just define a property named rightView in OMNLeftViewController.h :
self.leftViewController.rightView = self.rightViewController;

Pressing a button on a custom keyboard is resulting in "Unrecognized selector being sent to instance error"

I know there are plenty of other questions addressing the same problem, but since I'm using a custom keyboard, I thought my problem would be slightly different.
This is the specific error:
-[EquationTextField element1Pressed:]: unrecognized selector sent to instance 0x4b68ee0
2012-01-02 12:23:44.630 rowQuiz[20975:207] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[EquationTextField element1Pressed:]: unrecognized selector sent to instance 0x4b68ee0'
I have a view controller, quizController. Inside quizController is a custom view, textField (added through interface builder).
When textField is tapped, another custom view, formulaKeyboard, pops up as its keyboard. When a button on the keyboard is pressed, method element1Pressed: is called, and the error described above appears.
Some other questions say that there must be a problem with the retain count, so I tried retaining and releasing quizController in the app delegate, which didn't solve the problem.
It is also possible that I hooked up something incorrectly in Interface Builder; For the custom keyboard, File's owner and the main view are set to class elementKeyboard. For quizController, File's owner is set to quizController and hooked up to it's view.
Below is the code of the textField's class.
EquationTextField.h
#import <UIKit/UIKit.h>
#import "FormulaKeyboard.h"
#interface EquationTextField : UIView <KeyInput> {
FormulaKeyboard *keyboard;
NSString *lastElement;
}
#property (readwrite, retain) UIView *inputView;
#end
EquationTextField.m
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
self.userInteractionEnabled = YES;
[self addGestureRecognizer:
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(becomeFirstResponder)]];
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:#"FormulaKeyboard" owner:self options:nil];
for (id object in bundle) {
if ([object isKindOfClass:[FormulaKeyboard class]])
keyboard = (FormulaKeyboard *)object;
}
self.inputView = keyboard;
keyboard.delegate = self;
}
return self;
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
#pragma mark -- KeyInput Protocol Methods
- (void)addElement:(NSString *)elementName {
}
- (void)addCharge:(NSString *)chargeIncrease {
}
- (void) addState:(NSString *)stateName {
}
- (void)deleteCharacter {
}
- (void)dealloc
{
[super dealloc];
}
formulaKeyboard.h
#import <UIKit/UIKit.h>
#protocol KeyInput <UITextInputTraits>
- (void) addElement:(NSString*) elementName;
- (void) addCharge:(NSString*) chargeIncrease;
- (void) addState:(NSString*) stateName;
- (void) deleteCharacter;
#end
#interface FormulaKeyboard : UIView {
id <KeyInput> delegate;
}
#property (nonatomic, retain) id <KeyInput> delegate;
-(IBAction) element1Pressed:(id)sender;
-(IBAction) element2Pressed:(id)sender;
-(IBAction) element3Pressed:(id)sender;
-(IBAction) element4Pressed:(id)sender;
-(IBAction) element5Pressed:(id)sender;
-(IBAction) element6Pressed:(id)sender;
-(IBAction) chargePlusPressed:(id)sender;
-(IBAction) chargeMinusPressed:(id)sender;
-(IBAction) solidSatePressed:(id)sender;
-(IBAction) liquidStatePressed:(id)sender;
-(IBAction) gasStatePressed:(id)sender;
#end
formulaKeyboard.m
- (IBAction)element1Pressed:(id)sender {
[delegate addElement:#"Na"];
}
- (void)element2Pressed:(id)sender {
[delegate addElement:#"N"];
}
- (void)element3Pressed:(id)sender {
[delegate addElement:#"O"];
}
- (void)element4Pressed:(id)sender {
}
- (void)element5Pressed:(id)sender {
}
- (void)element6Pressed:(id)sender {
}
appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
quizController = [[QuizController alloc] initWithNibName:#"QuizController" bundle:nil];
[self.window addSubview:quizController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[quizController release];
[super dealloc];
}
The action of the keyboard's buttons are pointing to the wrong place. You've probably got them wired to File's Owner inside the FormulaKeyboard nib when they should be wired to the FormulaKeyboard object you're creating inside the nib.
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:#"FormulaKeyboard" owner:self options:nil];
That's being called from EquationTextField, so self would be your instance of EquationTextField. If you're keyboard's targets are pointing there, that's why you get the unrecognized selector exception.
What's happening here is a method called element1Pressed: is being sent to an instance of EquationTextField. You need to actually add the method to the class for it to work. Right now, it's sending the message to the field class, but there's no matching method, so it's throwing an error.
Also, I can't be completely sure about this, since you haven't posted the whole code and/or NIB info, but it seems that you may be going about this the wrong way. You should be using a view controller to handle everything, rather than a custom text field class. I notice that you haven't posted any code for the QuizController class. Once you do so, I may be able to give you more advice.
EDIT: Now that you've posted more code, I think I see the problem. You want the FormulaKeyboard instance to receive the event, but the event is linked to the EquationTextField instance instead. Make sure you wire it to an instance of FormulaKeyboard instead.
On the other hand, it seems that you may not have an instance of FormulaKeyboard in the NIB at all. Add an NSLog after keyboard = (FormulaKeyboard *)object to test if keyboard is ever actually assigned a value. If the NSLog doesn't fire, double-check that you've actually added an instance of FormulaKeyboard to the NIB.

Change From a UIView to a UITableView

im a begginer Objective-c programmer and i stuck at this point. I Created an App from the View Template, then edited the view xib and add a button and assigned it to the showEdicoes function, but when i click it, it does execute the function(i tested with breakpoints) but it doesnt do anything, if i click again it gives an EXEC_BAD_ACESS
Codes:
bipViewController.h (the default one created by the template)
#import <UIKit/UIKit.h>
#import "edicoesVC.h";
#interface bipViewController : UIViewController {
edicoesVC *EdVC;
}
#property(nonatomic,retain)edicoesVC *EdVC;
- (IBAction) showEdicoes:(id)sender;
#end
bipViewController.m
#import "bipViewController.h"
#implementation bipViewController
#synthesize EdVC;
- (IBAction) showEdicoes:(id)sender {
edicoesVC *Edic = [[edicoesVC alloc] initWithNibName:#"edicoesVC" bundle:[NSBundle mainBundle]];
self.EdVC = Edic;
[Edic release];
[self.navigationController pushViewController:self.EdVC animated:YES];
[self.EdVC release];
}
.....
#end
edicoesVC.h and edicoesVC.m are the TableViewController to which i wan to change to.
i didnt changed anything on the appDelegate
what i missed?
Thanks i advance
EDIT: Additional code
bipAppDelegate.h
#import <UIKit/UIKit.h>
#class bipViewController;
#interface bipAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
bipViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet bipViewController *viewController;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
bipAppDelegate.m
#import "bipAppDelegate.h"
#import "bipViewController.h"
#implementation bipAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize navigationController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
/*
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.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
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, called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
/*
Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
/*
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.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
See also applicationDidEnterBackground:.
*/
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
*/
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
edicoesVC.h
#import <UIKit/UIKit.h>
#interface edicoesVC : UITableViewController {
}
#end
edicoes.m
#import "edicoesVC.h"
#implementation edicoesVC
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 1;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
if(indexPath.row == 0) {[cell setText:#"Janeiro 1918"];}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 0)
{
}
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
I suspect the EXEC_BAD_ACCESS arises from the line:
[self.EdVC release];
This is because you have declared EdVC as (nonatomic, retain) in the header. This will perform a release followed by a retain when it is assigned a new value but you are performing an extra release. Take out the [self.EdVC release] line and move it to dealloc as:
[EdVC release];
Give this a try as it's the only thing I can think of, based on the code you've posted.
On the problem of nothing happening, I can't tell what's wrong from the code posted. Could you post the startup code of edicoesVC.h/edicoesVC.m?
You are using "self.EdVC" which is what I believe is causing your problem. When you access properties, just use the property name. For example:
[EdVC release];
One more thing, when coding in Objective-C classes are usually capitalized (i.e., BipViewController) and variables are lower case, i.e., eDic).

how to direct the Facebook button to a certain view controller

I have created a login button for my application, the login and the logout features work for the application. the problem i am having at the moment is that once the user has logged in to the application it only displays a logout button. i would like the application to direct the segue to my main view controller. [once the user logged in it displays this screen, i would like the user to be direct to the main home screen][1]
this is the main screen of the application, i would like the user to enter there login detail, once that has been a success i would like the user to be taken to this screen
the following code for the login screen and my app delegate
//
// AppDelegate.m
// SMAApplication
//
// Created by MOHAMMED Shakeel on 23/03/2016.
// Copyright © 2016 MOHAMMED Shakeel. All rights reserved.
//
#import "AppDelegate.h"
#import "AppDelegate.h"
#import "DetailViewController.h"
#import "Masterviewcontroller.h"
#import "data.h"
#import "FBSDKCoreKit/FBSDKCoreKit.h"
#import <FBSDKLoginKit/FBSDKLoginKit.h>
#interface AppDelegate ()
#end
#implementation AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application {
[FBSDKAppEvents activateApp];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
[[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
// Override point for customization after application launch.
[data getallNotes];
return YES;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
#pragma mark - Core Data stack
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "Shakeel.StudentManagementApplication" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"StudentManagementApplication" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
#import "LoginViewController.h"
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import "FBSDKLoginKit/FBSDKLoginKit.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
loginButton.center = self.view.center;
[self.view addSubview:loginButton];
}
#pragma mark - Navigation
//In astoryboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
- (IBAction)login:(id)sender {
[self performSegueWithIdentifier:#"main" sender:self];
}
#end
You can use the delegate method of the FBSDKLoginButton - FBSDKLoginButtonDelegate.
-(void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error
{
[self performSegueWithIdentifier:#"Segueid"sender:self];
}
This method will get called on successful sign in via Facebook.