I am new to Objective-c and Xcode, yet I believe I know enough about it to realize that something is going wrong here. I have an application using a storyboard, and one of the views in the application is not running its viewDidLoad method. I am not sure if this is relevant, but I had recently accidentally deleted my original storyboard, and had to make another one. The original had worked great with no problems, yet when I use the new one, it does not work. The view in question is also the first view of a Tab Bar Controller, which might be part of the problem.
Here is the code from the class responsible for the view (.h):
#import <UIKit/UIKit.h>
#interface TabSynth : UIViewController
#property (nonatomic, retain) IBOutlet UIImageView *tomeWater;
#property (nonatomic, retain) IBOutlet UIImageView *tomeFire;
#property (nonatomic, retain) IBOutlet UIImageView *tomeAir;
#property (nonatomic, retain) IBOutlet UIImageView *tomeEarth;
#property (nonatomic, retain) IBOutlet UIImageView *tomeDark;
#property (nonatomic, retain) IBOutlet UIImageView *tomeLight;
#property (nonatomic, retain) IBOutlet UIButton *airSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *darkSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *earthSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *fireSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *lightSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *waterSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv1;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeWater1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeFire1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeAir1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeEarth1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeDark1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeLight1;
And here is the code from the (.m):
#import "TabSynth.h"
#implementation TabSynth
#synthesize tomeWater;
#synthesize tomeFire;
#synthesize tomeAir;
#synthesize tomeEarth;
#synthesize tomeDark;
#synthesize tomeLight;
#synthesize tomeWater1;
#synthesize tomeFire1;
#synthesize tomeAir1;
#synthesize tomeEarth1;
#synthesize tomeDark1;
#synthesize tomeLight1;
#synthesize airSynthButton;
#synthesize darkSynthButton;
#synthesize earthSynthButton;
#synthesize fireSynthButton;
#synthesize lightSynthButton;
#synthesize waterSynthButton;
#synthesize synthButtonLarv;
#synthesize synthButtonAmoeb;
#synthesize synthButtonLarv1;
#synthesize synthButtonAmoeb1;
-(void)viewDidLoad {
extern int gTomeAir;
extern int gTomeDark;
extern int gTomeEarth;
extern int gTomeFire;
extern int gTomeLight;
extern int gTomeWater;
extern int gAmoebaeNum;
extern int gLarvaeNum;
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
if (gTomeAir>0) {
tomeAir.hidden=NO;
tomeAir1.hidden=YES;
airSynthButton.hidden=NO;
}
if (gTomeDark>0) {
tomeDark.hidden=NO;
tomeDark1.hidden=YES;
darkSynthButton.hidden=NO;
}
if (gTomeEarth>0) {
tomeEarth.hidden=NO;
tomeEarth1.hidden=YES;
earthSynthButton.hidden=NO;
}
if (gTomeFire>0) {
tomeFire.hidden=NO;
tomeFire1.hidden=YES;
fireSynthButton.hidden=NO;
}
if (gTomeLight>0) {
tomeLight.hidden=NO;
tomeLight1.hidden=YES;
lightSynthButton.hidden=NO;
}
if (gTomeWater>0) {
tomeWater.hidden=NO;
tomeWater1.hidden=YES;
waterSynthButton.hidden=NO;
}
if (gAmoebaeNum > 0) {
synthButtonAmoeb.hidden=NO;
synthButtonAmoeb1.hidden=YES;
}
else {
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
}
if (gLarvaeNum >= 1) {
synthButtonLarv.hidden=NO;
synthButtonLarv1.hidden=YES;
}
else {
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
}
}
In the if statements, the external integers being called (gTome) were set equal to a number in the previous view. Any help at all would be great, and I apologize for the simpleness of my coding.
If it's not calling viewDidLoad, then the first thing to check is that in your storyboard you have properly set TabSynth as the custom class of your view controller. Also, I don't see an NSLog in your viewDidLoad method. How do you know it's not being called?
By the way, did you know that you can put non-UI objects in a nib or storyboard? I think this might help you simplify your code. For example, you could have a class ElementViews defined like this:
ElementViews.h
#interface ElementViews : NSObject
#property (assign, nonatomic) IBOutlet UIImageView *tome;
#property (assign, nonatomic) IBOutlet UIButton *synthButton;
#property (assign, nonatomic) IBOutlet UIImageView *tome1;
#end
and then in your TabSynth class, instead of three outlets for every element, you just have one outlet:
TabSynth.h
#class ElementViews;
#interface TabSynth : UIViewController
#property (nonatomic, retain) IBOutlet ElementViews *waterViews;
#property (nonatomic, retain) IBOutlet ElementViews *fireViews;
#property (nonatomic, retain) IBOutlet ElementViews *airViews;
#property (nonatomic, retain) IBOutlet ElementViews *earthViews;
#property (nonatomic, retain) IBOutlet ElementViews *darkViews;
#property (nonatomic, retain) IBOutlet ElementViews *lightViews;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv1;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb1;
...
In your storyboard, you drag a generic "Object" (looks like an orange cube) into your TabSynth scene. Change its custom class to ElementViews and its identity label to Water Views. Connect the waterViews outlet of the TabSynth to this new ElementViews object, and connect the outlets of the ElementViews object to the three water views (the tome and tome1 image views and the synthButton button). Repeat for the other five elements.
Then you can simplify your viewDidLoad method like this:
- (void)configureElementViews:(ElementViews *)elementViews state:(int)state {
if (state > 0) {
elementViews.tome.hidden = NO;
elementViews.tome1.hidden = YES;
elementViews.synthButton.hidden = NO;
}
}
- (void)viewDidLoad {
extern int gTomeAir;
extern int gTomeDark;
extern int gTomeEarth;
extern int gTomeFire;
extern int gTomeLight;
extern int gTomeWater;
extern int gAmoebaeNum;
extern int gLarvaeNum;
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
[self configureElementViews:self.waterViews state:gTomeWater];
[self configureElementViews:self.fireViews state:gTomeFire];
[self configureElementViews:self.airViews state:gTomeAir];
[self configureElementViews:self.earthViews state:gTomeEarth];
[self configureElementViews:self.darkViews state:gTomeDark];
[self configureElementViews:self.lightViews state:gTomeLight];
}
ok but you must write [super viewDidLoad] at the beginning of the method -viewDidLoad to call the viewDidLoad of the Controller itself (the father or its predecessor in the hierarchy of object) before writing your superb code which create a derived version of -viewDidLoad.
voila, good luck.
Related
First time using XCODE and Objective C. Having an issue with my UIButtons and UILabels becoming nil during my SKProductRequest method.
Below is my ShopViewController.m, where initially call my 3 UIButtons and my UILabel. In the viewDidLoad my UIButtons and Label have content.
My Shop page loads correctly but once the ProductsRequest method is called the UIButtons and UILabels become nil, not sure why. All the items are (strong, nonatomic) properties in the .h file and have been linked to the referencing Outlets in the ShopViewController. Any help is really appreciated.
ShopViewController.m below the product request is made with the GetProductInfo method. Which is called from my *homeViewController when I press the buy button on the main game viewController.
#import "ShopViewController.h"
#import "ViewController.h"
#interface ShopViewController ()
#property (strong, nonatomic) ViewController *homeViewController;
#end
#implementation ShopViewController
#synthesize fvProductTitle;
- (void)viewDidLoad {
[super viewDidLoad];
_fvBuyButton.enabled = YES;
_ddBuyButton.enabled = NO;
_bundleBuyButton.enabled = NO;
fvProductTitle.text = #"don't read this";
}
- (IBAction)buyFVProduct:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_fvProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction)buyDDProduct:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_ddProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction)buyBundleProduct:(id)sender {
SKPayment *payment = [SKPayment paymentWithProduct:_bundleProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) getProductInfo:(ViewController *) viewController {
_homeViewController = viewController;
if ([SKPaymentQueue canMakePayments])
{
SKProductsRequest *request = [[SKProductsRequest alloc]
initWithProductIdentifiers:
[NSSet setWithObjects:self.bundleProductID, self.ddProductID, self.fvProductID, nil]];
request.delegate = self;
[request start];
}
else{
_fvProductDescription.text = #"please enable app purchases";
}
}
#pragma mark -
#pragma mark SKProductsRequestDelegate
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *products = response.products;
if (products.count != 0)
{
_fvProduct = products[2];
_fvBuyButton.enabled = YES;
fvProductTitle.text = _fvProduct.localizedTitle;
_ddProduct = products[1];
_ddBuyButton.enabled = YES;
_ddProductTitle.text = _ddProduct.localizedTitle;
_bundleProduct = products[0];
_bundleBuyButton.enabled = YES;
_bundleProductTitle.text = _bundleProduct.localizedTitle;
} else {
fvProductTitle.text = #"Full Version Product not found";
_ddProductTitle.text = #"Dirty Dozen Product not found";
_bundleProductTitle.text = #"Bundle Product not found";
}
products = response.invalidProductIdentifiers;
}
#pragma mark -
#pragma mark SKPaymentTransactionObserver
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
[self unlockFullVersion];
[[SKPaymentQueue defaultQueue]
finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
NSLog(#"Transaction Failed");
[[SKPaymentQueue defaultQueue]
finishTransaction:transaction];
break;
default:
break;
}
}
}
Here is my ShopViewController.h to see properties I have set up.
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
#interface ShopViewController : UIViewController <SKPaymentTransactionObserver, SKProductsRequestDelegate> {
}
#property (nonatomic) BOOL *isFullVersionAvailable;
// Store Kit
#property (strong, nonatomic) SKProduct *fvProduct;
#property (strong, nonatomic) SKProduct *ddProduct;
#property (strong, nonatomic) SKProduct *bundleProduct;
#property (strong, nonatomic) NSString *fvProductID;
#property (strong, nonatomic) NSString *ddProductID;
#property (strong, nonatomic) NSString *bundleProductID;
#property (strong, nonatomic) IBOutlet UIButton *fvBuyButton;
#property (strong, nonatomic) IBOutlet UIButton *ddBuyButton;
#property (strong, nonatomic) IBOutlet UIButton *bundleBuyButton;
#property (strong, nonatomic) IBOutlet UILabel *fvProductTitle;
#property (strong, nonatomic) IBOutlet UILabel *ddProductTitle;
#property (strong, nonatomic) IBOutlet UILabel *bundleProductTitle;
#property (strong, nonatomic) IBOutlet UITextView *fvProductDescription;
- (IBAction)buyFVProduct:(id)sender;
- (IBAction)buyDDProduct:(id)sender;
- (IBAction)buyBundleProduct:(id)sender;
- (void)getProductInfo:(UIViewController *)viewController;
#end
My ViewController.m below, my purchaseItem is what the user presses to transition to the shop page and calls the getProductInfo method.
- (IBAction)purchaseItem:(id)sender {
shopViewController.fvProductID = #"BurnsyBadges.FullVersion";
shopViewController.ddProductID = #"BurnsyBadges.DirtyDozen";
shopViewController.bundleProductID = #"BurnsyBadges.Bundle";
[shopViewController getProductInfo: self];
}
To Answer my own question. I had figured it out a few weeks ago and didn't get to update this. But it was a few things I had to correct in order to get multiple ViewControllers to access the Product Purchase Page correctly.
To get the one page working I needed to add a NavigationController to all my ViewControllers.
I have some problem with this library and my objects,I have 3 kind of object:
page, widget, gallery
page:
int
string
dictionary of widget
widget:
int
string
dictionary gallery
gallery
int
string
array page
I create all protocol so I create something like:
page:
import widget
int
string
dict<Widget>
widget
import gallery
int
string
Gallery
dict<Gallery>
Gallery
import page
int
string
array<Page>
after I create delegate and all this I get "unknow type" error and cannot find protocol...where is the error?
You need to define protocol and import the header file
//Page.h
#protocol Page
#end
#class Widget;
#interface Page : JSONModel
#property (nonatomic, assign) NSInteger pageID;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) Widget *widget;
//Widget.h
#class Gallery;
#interface Widget : JSONModel
#property (nonatomic, assign) NSInteger widgetID;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) Gallery *gallery;
//Gallery.h
#import "Page.h"
#interface Gallery : JSONModel
#property (nonatomic, assign) NSInteger galleryID;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSArray<Page>* pages;
When I tried to execute this XCODE an error occured. Can anyone help me understand it please? The Error is at line 5.
#import <UIKit/UIKit.h>
#interface BIDViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *numberField;
#property (weak, nonatomic) IBOutlet UITextField *nameField;
- (IBAction)textFieldDoneEditing:(id)sender;
[sender resignFirstResponder];
#end
Thanks.
[sender resignFirstResponder];
You can't do that in a .h file. Remove it. That belongs in .m.
in .h
#import <UIKit/UIKit.h>
#interface BIDViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *numberField;
#property (weak, nonatomic) IBOutlet UITextField *nameField;
- (IBAction)textFieldDoneEditing:(id)sender;
in .m
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
I need to use several times:
[mutableDict addEntriesFromDictionary:dictionary];
I don't know how to declare mutableDict in the header file. I try with:
#property (nonatomic, assign) NSMutableDictionary *mutableDict;
#property (nonatomic, retain) NSMutableDictionary *mutableDict;
#property (nonatomic, retain, readwrite) NSMutableDictionary *mutableDict;
And more...
How I must to declare this NSMutableDictionary??
In your header file use #property (nonatomic, retain) NSMutableDictionary *mutableDict; if your are not using ARC, or #property (nonatomic, strong) NSMutableDictionary *mutableDict; if you are using ARC.
In your implementation include #synthesize mutableDict; or better #synthesize mutableDict = _mutableDict; somewhere after #implementation YourClass.
You should also initialize it with something like _mutableDict = [[NSMutableDictionary alloc] init];
If you do not need your mutable dictionary used from outside (ex: [myobject.mutableDict addEntriesFromDictionary:dictionary]; you better not define it in your header file but in your implementation like:
#implementation YourClass {
NSMutableDictionary *_mutableDict;
}
and initialize it like shown above
I have this managedObject subclass, position rappresent a NSPoint. In a XIB I want two NSTextField like this
where one display position.x value and the other display position.y. I tried to bind the NSTextField to a "selection.position.x" and "selection.position.y" keyPath of a NSArrayController that manage Frames
I get this error::
[ setValue:forUndefinedKey:]: this class
is not key value coding-compliant for the key x.
So i checked KVC:
Frame.h
#interface Frame : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * order;
#property (nonatomic, retain) NSNumber *visible;
#property (nonatomic, retain) NSValue *position;
#property (nonatomic, retain) NSNumber *scale;
#property (nonatomic, retain) Sprite *sprite;
#property (nonatomic, retain) Resource *resource;
//test
#property (nonatomic, retain) NSValue *frame;
#end
In -(void)awakeFromInsert I try this code:
-(void)awakeFromInsert
{
[super awakeFromInsert];
self.position = [NSValue valueWithPoint:NSPointFromCGPoint(CGPointZero)];
//[self.position setValue:[NSNumber numberWithFloat:50.0f] forKey:#"x"];
[self setValue:[NSNumber numberWithFloat:1.0f] forKeyPath:#"scale"];
[self setValue:[NSNumber numberWithFloat:10.0f] forKeyPath:#"frame.origin.x"];
[self setValue:[NSNumber numberWithFloat:10.0f] forKeyPath:#"position.x"];
}
The first and second KVC setValue works, the third crash with the same message above
[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key x.
I don't understand why, any help is appreciate.
NSValue objects are not mutable. To change a NSValue property, you have to create a new NSValue object and then assign it to the property.