NSUserDefaults NSColor extension error - objective-c

This is my first time creating an extension and I'm extending NSUserDefaults. I'm just using the code that I found on Apple's developer page, but I'm getting errors in the project in my .h and .m files. I created the files for macOS as the Cocoa class type. How can I fix this? Here's the code along with the errors:
NSUserDefaults+MyColourSupport.h
#import <Foundation/Foundation.h>
#interface NSUserDefaults(MyColourSupport)
-(void)setColor:(NSColor *)aColor forKey:(NSString *)aKey;
-(NSColor*)colorForKey:(NSString *)aKey;
#end
NSUserDefaults+MyColourSupport.m
#import "NSUserDefaults+MyColourSupport.h"
#implementation NSUserDefaults(MyColourSupport)
-(void)setColor:(NSColor*)aColor forKey:(NSString*)aKey {
NSData *theData = [NSArchiver archivedDataWithRootObject:aColor];
[self setObject:theData forKey:aKey];
}
-(NSColor*)colorForKey:(NSString*)aKey {
NSColor *theColor = nil;
NSData *theData = [self dataForKey:aKey];
if (theData != nil)
theColor = (NSColor*)[NSUnarchiver unachiveObjectWithData:theData];
return theColor;
}
#end

Related

Objective c + Tesseract issue

I've simple code that performs recognition text on image as below:
#import "ParseLinesFromImage.h"
#import <TesseractOCR/TesseractOCR.h>
#implementation ParseLinesFromImage
- (void) performRecognitionWithImage:(UIImage*)image
{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
G8Tesseract* tesseract = [[G8Tesseract alloc] initWithLanguage:#"eng"];
tesseract.language = #"eng";
tesseract.engineMode = G8OCREngineModeTesseractCubeCombined;
tesseract.pageSegmentationMode = G8PageSegmentationModeAuto;
tesseract.maximumRecognitionTime = 60.0;
tesseract.image = [image g8_blackAndWhite];
BOOL recognized = [tesseract recognize];
if (recognized == YES)
{
NSDictionary *array = [self parseValidLines:tesseract.recognizedText];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate sucessWithText:array];
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate failedTextReader:nil];
});
}
});
}
Code define in .h file like below:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol ParseLinesFromImageDelegate<NSObject>
#required
-(void) sucess:(nullable NSDictionary*)info;
-(void) failed:(nullable NSError*) error;
#end
#interface ParseLinesFromImage: NSObject
#property (nonatomic, weak, nullable) id <ParseLinesFromImageDelegate> delegate;
- (void) performRecognitionWithImage:(UIImage* _Nonnull)image;
#end
But when running to line marked as 1, system push an exeption
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImage g8_blackAndWhite]: unrecognized selector sent to instance 0x60c0000b9e00'"
In my view it may be an ambiguous between UIImage+G8Filters.h(define g8_blackAndWhite) and UIImage but I look into TesseractOCR example, it's the same as mine.
Please help me to find out the reason and how to fix it, thanks.
PS: Thanks you for reading my question, after google and follow answer from https://github.com/gali8/Tesseract-OCR-iOS/wiki/Installation (side note), the issue goes away and in my case, I added _all-load to my project.

Objective-C: Assigning a value to a static remains nil?

I have the following defined in a header file:
static NSArray *knownPrinters = nil;
In a test case:
knownPrinters = [NSArray new];
I have a breakpoint before and after that single line and the value of knownPrinters remains nil despite being assigned. There is only the main thread and I running only one unit test.
Am I going crazy or is there a legitimate reason why this would occur?
I defined your global variable by using extern keyword as rmaddy suggested and it is allocated in a unit test under the same conditions you described. Here is the code
// Header file
#import <Foundation/Foundation.h>
extern NSArray *knownPrinters;
#interface DummyObject : NSObject
#end
Here is the implementation file
#import "DummyObject.h"
NSArray *knownPrinters = nil;
#implementation SingletonObject
#end
And test file,
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "DummyObject.h"
#interface SOStaticAssignTests : XCTestCase
#end
#implementation SOStaticAssignTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testExample {
knownPrinters = [NSArray new];
NSLog(#"For debugging");
}
#end
I hope it solves your problem.

Access Variables in different classes and Globals in objective c

in my app i have multiple classes :D, the thing is i need to access a variable from class a in class b. For this purpose i use synthesize, i declare my variable in my .h between interface brackets, then declare a property of the variable wich is a NSString. Then i use synthesize :). But when i access it in class b i have a NSString equal to nil :§. When i breakpoint to check if the NSString get filled it works the NSLog shows the right string in the classe a, but in class b i got nil :§. Secondly i would like to have your opinion : it is better to use a global like NSUserDefaults or a old school c global declaration or this "synthesize" way of doing it ? If anyone would like to help me please, thank you a lot :).
//polymorphViewController.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "LCYDataBackedTableView.h"
#import "RootViewController.h"
#import "LCYLockSettingsViewController.h"
#import "LockScreenAppDelegate.h"
#import "MyWebViewController.h"
#import "MemberViewController.h"
#import "SharedViewController.h"
#import "UploadedViewController.h"
#interface PolymorphViewController : LCYDataBackedTableView{
NSString *secondId;
}
#property (readwrite,nonatomic) NSString *secondId;
#end
//in class a .h
#interface firstViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>{
IBOutlet UITableView * newsTable;
UISearchBar *searchBar;
UISearchDisplayController *searchDisplayController;
...
NSString *idNumber;
}
#property (readwrite, retain) NSString *idNumber;
- (void)launchIt:(NSString *)typeofdata sharedOrUploaded:(BOOL)smogogo;
#end
//in class a .m
#implementation firstViewController
#synthesize idNumber
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
idNumber = [[stories objectAtIndex: storyIndex] objectForKey: #"sizing_id"];
PolymorphViewController *polymorph = [[PolymorphViewController alloc]init];
[[self navigationController] pushViewController:polymorph animated:YES];
[polymorph viewDidLoad];
}
//in class B .m
-(void)dataByChoice: (NSString *)command{
self.title = #"Test";
myWebView = [[UIWebView alloc] initWithFrame:self.view.frame];
[self.view addSubview:myWebView];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *defaults = [prefs stringForKey:#"myKey"];
NSString *defaults2 = [prefs stringForKey:#"mySecondKey"];
NSString *username = defaults;
NSString *password = defaults2;
firstViewController *WC = [[firstViewController alloc]initWithNibName:nil bundle:nil];
NSLog(WC.idNumber); <-- equals nil :(
NSString *idName = WC.idNumber;
NSString *partialUri = [#"http://www.google.com" stringByAppendingString: idName];
NSString *finalUri = [partialUri stringByAppendingString: command];
NSURL *url = [NSURL URLWithString:finalUri];
your class be should look like this .h file
#interface Class_B : UIViewController
#property (copy,nonatomic) NSString *someValue;
#end
.m file
#implementation Class_B
#synthesize someValue = _someValue;
- (void) viewDidLoad {
_someValue = #"This is my come value";
}
#end
and calling class (Class_A) it should be like this
- (void) viewDidLoad {
Class_B *cls_b = [[Class_B alloc] initWithNibName:#"Class_B_nib" bundle:nil];
NSLog(#"Some value echo :%#",cls_b.someValue);
}
Use NSUserDefaults when you need to store locally data among sessions of the app, I would not use it just to share variables among classes.
#synthesize directive is used to generate accessors methods for properties (nowadays, unless you want to change the name of setters and getters, you don't even need it) declared with #property directive.
If you just need to access the property from another object then a property declared in the interface file (.h) is perfect. If you need to share a property across the app, I am thinking about the singleton pattern but there are definitely many ways to do it.

Singleton data out of scope problem

I am trying to pass data between the viewcontrollers of a uitabbarcontroller using a singleton class as below:
#import <Foundation/Foundation.h>
#interface AppSingleton : NSObject {
NSMutableString *selectedStr;
}
#property(nonatomic,retain) NSMutableString *selectedStr;
+(AppSingleton*) sharedAppInstance;
#end
Here is my implementation file:
#import "AppSingleton.h"
#implementation AppSingleton
#synthesize selectedStr;
+(AppSingleton*) sharedAppInstance{
static AppSingleton *sharedAppInstance;
#synchronized(self){
if(!sharedAppInstance){
sharedAppInstance = [[AppSingleton alloc] init];
}
}
return sharedAppInstance;
}
-(void)dealloc{
[selectedStr release];
[super dealloc];
}
#end
I try to set the selectedStr in one of my viewcontrollers as below and print it in the NSLog however I get a null:
AppSingleton *sharedAppInstance;//in the header
sharedAppInstance = [AppSingleton sharedAppInstance];//in viewdidload
[sharedAppInstance setSelectedStr:self.someStr];
NSLog(#"selectedStr is: %#", sharedAppInstance.selectedStr);
When I debug this, the sharedAppInstance.selectedStr seems to be out of scope.
I would like to know where I am making a mistake.
Thank you.
I changed the placing of the setting/getting of my variable within the viewcontroller and it worked..
[sharedAppInstance setSelectedStr:self.someStr];
NSLog(#"selectedStr is: %#", sharedAppInstance.selectedStr);

Memory leak for object in array

I've started cleaning up my app before publication - using "Instruments" Leak analyzer.
I found a leak I can't plug. So I built a simple project to illustrate the problem. Please see code below. I put a button on the view to test fire the procedure "test". It always generates a leak.
First the header and code for an object named "theObj"
#import <Foundation/Foundation.h>
#interface theObj : NSObject {
NSString* theWord;
}
#property (nonatomic,retain) NSString* theWord;
#end
#import "theObj.h"
#implementation theObj
#synthesize theWord;
-(id) initWithObjects: (NSString *) aWord;
{
if (self = [super init]){
self.theWord = aWord;
}
return self;
}
-(void) dealloc{
[theWord release];
[super dealloc];
}
#end
Now the view controller
#import <UIKit/UIKit.h>
#import "theObj.h"
#interface LeakAnObjectViewController : UIViewController {
NSMutableArray* arrObjects;
}
- (IBAction)test;
#end
#import "LeakAnObjectViewController.h"
#implementation LeakAnObjectViewController
- (IBAction)test {
if (arrObjects == nil)
arrObjects = [[NSMutableArray alloc] init];
NSString* aStr = #"first";
[arrObjects addObject:[[theObj alloc] initWithObjects:aStr]];
[arrObjects removeAllObjects];
}
You alloc the object, which means you own it. Then you give it to the array, which means the array owns it as well. Then the array removes it, so you are the only owner. But you don't have a reference to the object anymore, so you can't release it, so it's just leaked.
Someone really needs to learn the rules around memory management. Specifically as it pertains to ownership, etc.