So I got this for loop in a function, but it never gets entered,
for (Window *window in _app.windows) {
NSLog(#"test.");
}
I'm a beginner so where do I start to debug this and see where it goes wrong?
EDIT
This is in another class
(its in a function (loadApp) that I call in my ViewController, like this: self.app = [MyClass loadApp]; , the above code is also in my ViewController.
Window *window = [[Window alloc] initWithName:title subtitle:subtitle number:number ident:ident type:type chapternumber:chapternumber icon:icon text:text img:img question:question answerFormat:answerFormat answerLength:answerLength tip1:tip1 tip2:tip2 tip3:tip3 tip1Answer:tip1Answer tip2Answer:tip2Answer tip3Answer:tip3Answer];
[app.windows addObject:window];
}
return app;
Try the following
if(!_app) {
NSLog(#"app is nil");
}
else if(!_app.windows) {
NSLog(#"windows is nil");
}
else {
NSLog(#"there are %d windows", [_app.windows count]);
}
I suspect you'll see there are 0 windows
You have to make sure you are accessing the same variable. That is the gist of all the other comments and answers you are getting. It needs to be setup something like this. Keep in mind, your app may not be setup exactly like this. This is just a general structure to follow:
//myViewController.h
#import "WindowClass.h"
#import "AppClass.h"
#property (strong, nonatomic) AppClass *app;
//myViewController.m
#import "myViewController.h"
#synthesize app;
(id)init....{
//...init code here
//Synthesized objects must be initialized before they are accessed!
self.app = [[AppClass alloc] init];
return self;
}
(void)loadApp {
WindowClass *aWindow = [[WindowClass alloc] init];
[self.app.windowArray addObject:aWindow];
return;
}
(void)loopFunction {
for (WindowClass *window in self.app.windowArray) {
NSLog(#"test.");
}
return;
}
//AppClass.h
#property (strong, nonatomic) NSArray *windowArray;
//AppClass.m
#import "AppClass.h"
#synthesize windowArray;
Related
I am trying to get the gps information from the RTK in DJI M600 Pro by using an ios app, I have looked at DJI Mobile SDK API reference, and I have found some RTK API . When the drone is starting up, the property "isRTKBeingUsed" should be "YES" ,but I can't get the result.
Any help would be greatly appreciated! Here is my code:
#import "ViewController.h"
#import <DJISDK/DJISDK.h>
#import "DJIAppActivationManager_InternalTesting.h"
#import<DJISDK/DJIRTK.h>
#define WeakRef(__obj) __weak typeof(self) __obj = self
#define WeakReturn(__obj) if(__obj ==nil)return;
void ShowResult(NSString *format, ...)
{...
}
#interface ViewController ()<DJIAppActivationManagerDelegate, DJISDKManagerDelegate,DJIRTKDelegate>
...
...
#property (weak, nonatomic) IBOutlet UILabel *isusing;
#property(strong, nonatomic) DJIRTK * rtk1;
#property(strong, nonatomic) DJIRTKState * rtkstate1;
#end
#implementation ViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self registerApp];
[self updateUI];
self.rtk1 = [[DJIRTK alloc] init];
self.rtkstate1 = [[DJIRTKState alloc] init];
[self rtk:_rtk1 didUpdateState:_rtkstate1];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void) rtk:(DJIRTK *)rtk didUpdateState:(DJIRTKState *)state
{
self.shifoushiyong.text = [NSString stringWithFormat:#"%d",state.isRTKBeingUsed];
}
- (void)registerApp
{
[DJISDKManager registerAppWithDelegate:self];
}
-(void)updateUI
{
...
}
...
#end
TLDR: You are using the RTK delegate method the wrong way.
didUpdateState: is a delegate method. You need to pass a delegate object to your RTK object. When data comes from the aircraft, didUpdateState will be called. You don't have to do it manually.
Furthermore, you shouldn't init your own RTK object:
1/ Once you have confirmation the SDK has registered (delegate method of DJISDKManager), get the product
- (void)appRegisteredWithError:(NSError *_Nullable)error {
DJISDKManager.product
// continue here
}
https://developer.dji.com/api-reference/ios-api/Components/SDKManager/DJISDKManager.html#djisdkmanager_product_inline
2/ Verify it's a DJIAircraft class
if ([[DJISDKManager.product class] isKindOf:[DJIAircraft class]) {
// Continue here
}
https://developer.dji.com/api-reference/ios-api/Products/Aircraft/DJIAircraft.html?search=djiaircraft&i=0&
3/ Get the RTK object from there:
DJIRTK *rtk = aircraft.flightController.RTK;
https://developer.dji.com/api-reference/ios-api/Components/FlightController/DJIFlightController.html#djiflightcontroller
4/ Set the delegate to RTK (a class that implemented DJIRTKDelegate - assuming self here)
rtk.delegate = self;
https://developer.dji.com/api-reference/ios-api/Components/RTK/DJIRTK.html#djirtk_protocol_inline
5/ Get the data in the delegate method like you did.
- (void)rtk:(DJIRTK *_Nonnull)rtk didUpdateState:(DJIRTKState *_Nonnull)state {
// Show me the data
}
https://developer.dji.com/api-reference/ios-api/Components/RTK/DJIRTK.html#djirtk_updatertkstate_inline
I have been creating a cocoa static library in which I have a public nsobject file where I created a custom delegate. In the app I imported the nsobject file and implemented the delegate but the delegate is not getting called... the static library name is glamApi.
the SKUIDPasser.h file of the NSObject in the library
#import <Foundation/Foundation.h>
#protocol SubClassDelegate <NSObject>
#required
- (void)MethodNameToCallBack:(NSString *)s;
#end
#interface SKUIDPasser : NSObject
-(void)getSKUIDsFromCart:(NSString *)SKUIDs;
#property (nonatomic, weak) id <SubClassDelegate> delegatePasser;
#end
and the SKUIDPasser.m file
#import "SKUIDPasser.h"
#implementation SKUIDPasser
#synthesize delegatePasser;
-(void)getSKUIDsFromCart:(NSString *)SKUIDs{
NSLog(#"getSKUIDsFromCart %#",SKUIDs);
[delegatePasser MethodNameToCallBack:SKUIDs];
}
#end
And the method is called from a Viewcontroller in static library
- (IBAction)CartShowEvent:(id)sender {
if (![cartBadge isHidden]) {
buyClicked = TRUE;
[self loadCart];
[self showCartItemsAll];
self.cartView.frame = self.view.bounds;
[self.view addSubview:self.cartView];
SKUIDPasser *pass = [[SKUIDPasser alloc] init];
[pass getSKUIDsFromCart:#"sssss"];
} else {
[Utilities alert:#"No products to display !!!"];
}
}
The Viewcontroller which the custom delegate has to be implemented Viewcontroller.h
#import <glamAPI/SKUIDPasser.h>
#interface ViewController : UIViewController<SubClassDelegate>{
SKUIDPasser *sk;
}
Viewcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
sk = [[SKUIDPasser alloc] init];
sk.delegatePasser = self;
NSLog(#"sk.delegatePasser %#",sk.delegatePasser);
}
- (void)MethodNameToCallBack:(NSString *)s
{
NSLog(#"MethodNameToCallBack %#",s);
}
I didn't get any error but the method is not calling..Please help me to resolve this
The very first thing you need to understand is that each instance object of a class is entirely different entity and maintains it's state separately.
In you case your have created an object of your static library in viewDidLoad: and set the delegate accordingly, but when you are making the call to method getSKUIDsFromCart, you are using a different instance for which you never set the delegate property. That's why there was no callback.
To solve this, you can set the delegate in method CartShowEvent: before making the call, something like this
SKUIDPasser *pass = [[SKUIDPasser alloc] init];
pass.delegatePasser = self;
[pass getSKUIDsFromCart:#"sssss"];
However i would suggest that you should use the instance variable of library which you already created in viewDidLoad:
- (IBAction)CartShowEvent:(id)sender {
if (![cartBadge isHidden]) {
buyClicked = TRUE;
[self loadCart];
[self showCartItemsAll];
self.cartView.frame = self.view.bounds;
[self.view addSubview:self.cartView];
//No need to create another object.
//SKUIDPasser *pass = [[SKUIDPasser alloc] init];
//Use the previously created instance object
[sk getSKUIDsFromCart:#"sssss"];
}
else {
[Utilities alert:#"No products to display !!!"];
}
}
The SKUIDPasser object that you are calling within (IBAction)CartShowEvent:(id)sender and the SKUIDPasser object that you are setting the delegate are NOT the same.
Just for a test, try calling the method [sk getSKUIDsFromCart:#"sssss"]; just after you set the delegate and you will see that it will be called because this instance has the delegate set correctly:
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
sk = [[SKUIDPasser alloc] init];
sk.delegatePasser = self;
[sk getSKUIDsFromCart:#"sssss"];
NSLog(#"sk.delegatePasser %#",sk.delegatePasser);
}
- (void)MethodNameToCallBack:(NSString *)s
{
NSLog(#"MethodNameToCallBack %#",s);
}
Update
I updated my answer to help you call the trigger from the static library
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
sk = [[SKUIDPasser alloc] init];
sk.delegatePasser = self;
/*
You now can pass this variable to the static library to get called
from there ...
example:
viewControllerOnStaticLibrary.passer = sk;
*/
NSLog(#"sk.delegatePasser %#",sk.delegatePasser);
}
- (void)MethodNameToCallBack:(NSString *)s
{
NSLog(#"MethodNameToCallBack %#",s);
}
Viewcontroller_in_static_library.h
#property (nonatomic, strong) SKUIDPasser *passer;
Viewcontroller_in_static_library.m
- (IBAction)CartShowEvent:(id)sender {
if (![cartBadge isHidden]) {
buyClicked = TRUE;
[self loadCart];
[self showCartItemsAll];
self.cartView.frame = self.view.bounds;
[self.view addSubview:self.cartView];
//now you are calling the same instance
[self.passer getSKUIDsFromCart:#"sssss"];
} else {
[Utilities alert:#"No products to display !!!"];
}
}
In some reason, I have to use a design pattern that an object remove itself from its container, consider the following code(ARC is enabled, LCDObject is an object class, LCDContainer is a container class), in the whole program, object 's reference count is always 1 until it is removed from the container(reference count become 0), as comment 2 mention, when [_container removeObject:self] return, the object's reference count is 0, it is dealloc, right?, but the process is still in the object's method -- "removeFromContainer", what would happen? Does the following code would be execute successfully? Does "removeFromContainer" can return successfully?
I run this code in Xcode, the "NSLog" in "removeFromContainer" can be invoked successfully, but I can't figure out why...
//-------------------------------------------------------------
#import <Foundation/Foundation.h>
#interface LCDContainer : NSObject
#property (strong, nonatomic) NSMutableArray *objects;
- (void)removeObject:(id)object;
- (id)addObject:(id)object;
#end
#implementation LCDContainer
- (id)init {
self = [super init];
if (self) {
_objects = [[NSMutableArray alloc] init];
}
return self;
}
- (id)addObject:(id)object {
[_objects addObject:object];
return object;
}
- (void)removeObject:(id)object {
[_objects removeObject:object];
}
#end
//-------------------------------------------------------------
#interface LCDObject : NSObject
#property (weak, nonatomic) LCDContainer *container;
- (id)initWithContainer:(LCDContainer*) container;
- (void)removeFromContainer;
#end
#implementation LCDObject
- (id)initWithContainer:(LCDContainer *)container {
self = [super init];
if (self) {
_container = container;
// (1) add the object to the Container, now its reference count is 1
//
[container addObject:self];
NSLog(#"add to container.");
}
return self;
}
- (void)removeFromContainer {
// (2) remove the object from the Container, now its reference count is 0,
// the object is delete, does the following "NSLog" would be invoked successfully?
//
[_container removeObject:self];
NSLog(#"remove from container.");
}
#end
//-------------------------------------------------------------
int main(int argc, const char * argv[]) {
#autoreleasepool {
LCDContainer *container = [[LCDContainer alloc] init];
[[LCDObject alloc] initWithContainer:container];
[[[container objects] objectAtIndex:0] removeFromContainer];
}
return 0;
}
I've not tried your code but I suspect it will work. sapi's suggestion (adding a breakpoint or NSLog on dealloc) is a good one to confirm, though.
Thee are two ways that ARC could be doing this. You can check the assembler if you're really interested.
The simplest is to assume that it's using autorelease, that is, when an object is removed from your container it gets added to the autorelease pool and is released (and dealloced) at the end of the current run loop.
The other way is to consider where ARC adds its retains and releases. This question notes that your remove method really looks like this:
- (void)removeObject:(id)object {
[object retain];
[_objects removeObject:object];
[object release];
}
The call to removeObject: may well have the same logic. This means that object does not get released as soon as the removeObject: call is completed; the object lifecycle is almost certainly (slightly) longer than that.
I'm having trouble making a shopping cart sort-of concept in my app. I have my AppDelegate (named ST2AppDelegate) that contains an NSMutableArray called myCart. I want RecipeViewController.m to pass an NSString object to myCart, but every time I pass it the NSString and use NSLog to reveal the contents of the array, it is always empty.
Can anyone please tell me what I am doing wrong? I have worked on this code for days, and there is a line of code in which I don't understand at all what's going on (in the RecipeViewController.m, labeled as such).
Any help would be so appreciated... I'm just a beginner. Here are the relevant classes:
ST2AppDelegate.h:
#import <UIKit/UIKit.h>
#interface ST2AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) NSMutableArray* myCart;
- (void)addToCart:(NSString*)item;
- (void)readCartContents;
#end
ST2AppDelegate.m:
#import "ST2AppDelegate.h"
#implementation ST2AppDelegate
#synthesize myCart;
// all the 'applicationDid...' methods...
- (void)addToCart:(NSString *)item
{
[self.myCart addObject:item];
}
- (void)readCartContents
{
NSLog(#"Contents of cart: ");
int count = [myCart count];
for (int i = 0; i < count; i++)
{
NSLog(#"%#", myCart[count]);
}
}
#end
RecipeDetailViewController.h:
#import <UIKit/UIKit.h>
#import "ST2AppDelegate.h"
#interface RecipeDetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel* recipeLabel;
#property (nonatomic, strong) NSString* recipeName;
#property (nonatomic, strong) IBOutlet UIButton* orderNowButton;
- (IBAction)orderNowButtonPress:(id)sender;
#end
RecipeDetailViewController.m:
#import "RecipeDetailViewController.h"
#implementation RecipeDetailViewController
#synthesize recipeName;
#synthesize orderNowButton;
// irrelevant methods...
- (IBAction)orderNowButtonPress:(id)sender
{
// alter selected state
[orderNowButton setSelected:YES];
NSString* addedToCartString = [NSString stringWithFormat:#"%# added to cart!",recipeName];
[orderNowButton setTitle:addedToCartString forState:UIControlStateSelected];
// show an alert
NSString* addedToCartAlertMessage = [NSString stringWithFormat:#"%# has been added to your cart.", recipeName];
UIAlertView* addedToCartAlert = [[UIAlertView alloc] initWithTitle:#"Cart Updated" message:addedToCartAlertMessage delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[addedToCartAlert show];
// add to cart (I don't understand this, but it works)
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) addToCart:recipeName];
// read cart contents
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) readCartContents];
}
#end
You need to initialize myCart when your application launches:
self.myCart = [[NSMutableArray alloc] init];
otherwise you are just attempting to add objects to a nil object which while it won't throw an exception because of the way objective-c handles nil objects it will not function as expected until you initialize it.
Do you ever initalize the shopping cart variable?
Try doing lazy instantiation.
-(NSMutableArray *) myCart{
if (!_myCart){
_myCart = [[NSMutableArray alloc] init];
}
return _myCart;
}
This way you will know it will always get allocated. Basically, this method makes it so that whenever someone calls your classes version of the object it checks to see if that object has been allocated and then allocates it if it has not. It's a common paradigm that you should employ with most of your objects.
This method should go in the app delegate (where the object was declared).
I have a barcode scanner on one view, and after the user has scanned the barcode, the app takes them to another view (BoilerDetails) where the barcode text field has been pre-filled.
I understand that the viewcontroller is null when it hasn't come into view and I can'tchange the UITextField text directly. This so far has given me an error.. How can I fix this?
BarcodeScannerViewController.m
BoilerDetailsViewController *viewCtrl = [[BoilerDetailsViewController alloc] initWithNibName:nil bundle:nil];
[viewCtrl setBarcode:strBarcode];
[self.navigationController pushViewController:viewCtrl animated:YES];
BoilerDetailsViewController.h
#interface BoilerDetailsViewController : SubViewControllerBase
#property (retain, nonatomic) NSString *barcode;
#property (retain, nonatomic) IBOutlet UITextField *barcodeField;
- (void)setBarcode:(NSString*)strBarcode;
#end
BoilerDetailsViewController.m
-(void)setBarcode:(NSString *)strBarcode
{
self.barcode = strBarcode;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[_barcodeField setText:self.barcode];
// Do any additional setup after loading the view from its nib.
}
-(void)setBarcode:(NSString *)strBarcode
{
self.barcode = strBarcode;
}
I think that these strings give you infinite loop. According to your logic you should use:
-(void)setBarcode:(NSString *)strBarcode
{
self.barcodeField.text = strBarcode;
}
or
#syntesize barcode = _barcode;
-(void)setBarcode:(NSString *)strBarcode
{
[_barcode autorelease];
_barcode = [strBarcode retain] //in case of no ARC
}
Depends on what you want (store a string or set a label).
you just have to synthesize the barcode and in ViewDidload just write this code [_barcodeField setText:barcode]; and good to Go.
First of all, this is wrong
-(void)setBarcode:(NSString *)strBarcode
{
self.barcode = strBarcode;
}
self.barcode = strBarcode; itself calls the setter.
depending on your ios version you shud write:
//for ARC environment
-(void)setBarcode:(NSString *)strBarcode
{
_barcode = strBarcode;
}
//since default association in ARC is strong
before this do #synthesize barcode = _barcode;
//and for non-ARC environment, since your property is retain type
-(void)setBarcode:(NSString *)strBarcode
{
if (_barcode != barcode) {
[_barcode release];
_barcode = [barcode retain];
}
}
And you will be OK.