j2objc java extends native uicolor - native

how can i extends the UIColor in java code example like using native methods.
So j2objc able to compile the java class extends with UIColor.
I'm not sure how to code the extends part.
Please help.

You can't with j2objc, as classes must by compilable by a Java compiler (such as javac), and there's no UIColor Java source or class file. That said, it would be easy to create your own color class that can create a UIColor when asked, something like:
class MyColor {
float red, green, blue, alpha;
...
native Object toUIColor() /*-[
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
]-*/;

Related

Is it possible to call Swift convenience initializer in Objective-C

Say I have a convenience initializer in Swift:
extension UIImage {
convenience init?(bundleNamed name: String) {
let bundle = NSBundle(forClass: Foo.self)
self.init(named: name, inBundle: bundle, compatibleWithTraitCollection: nil)
}
}
How might I call this in Objective-C? The following doesn't work:
[UIImage bundleNamed:#"Bar"];
[[UIImage alloc] initWithBundleNamed:#"Bar"];
Do I need an additional class extension solely for Objective-C?
Solution: following Lasse's answer below, the steps I had to do were:
In the Objective-C classes implementation file, add
#import <ModuleName-Swift.h>
then I had to delete derived data and rebuild. Then I was able to use the convenience initializer as follows:
[[UIImage alloc] initWithBundleNamed: #"Bar"];
I didn't need to declare the initializer as public because the default level of internal was sufficient for my module.
Check out Using Swift with Cocoa and Objective-C (Swift 2.2) - Mix and Match. What it seems to come down to is
Making your convenience initializer public, and
Importing an XCode-generated header file [YourProductModuleName]-Swift.h into your code
Yes we can use it Note: #objc and public are important
#objc public init(url: URL) {
//your code
}
Please note! If you are using any of Swift features that are not available in Objective-C (like Optional values), it would not be accessible in Objective-C.
So fix them.
public convenience init(title:String?, message:String?) {
self.init()
self.title = title
self.message = message
}
Above code is not accessible, so removing optional will help in this case.

use OCMockito to test category class method

I have a UIColor category that has a class method
+(UIColor *)appropriateTextColorForBackground:(UIColor *)background
{
//...get brightness value
if (brightness > 127.5f)
return [UIColor blackColor];
else
return [UIColor whiteColor];
}
I want to test with OCMockito using this in my test class
-(void)testAppropriateColorWithBlackShouldReturnWhiteColor
{
Class color = mockClass([UIColor class]);
[color appropriateTextColorForBackground:black];
assertThat([color testColorWithColor:black], is([UIColor whiteColor]));
}
but I get the error
test failure: -: *** -[NSProxy doesNotRecognizeSelector:appropriateTextColorForBackground:] called!
what am I missing? it seems that this should work
I agree with Bryan, that you don't need mock here since you want to test your implementation of category method. As example:
-(void)testAppropriateColorWithBlackShouldReturnWhiteColor
{
UIColor *appropriateColor = [color appropriateTextColorForBackground:black];
assertThat(appropriateColor, is(equalTo([UIColor whiteColor])));
}
You also probably want to have similar test for opposite color. I would probably go further and will use colors that are on the border of change for you brightness calculation (instead of black and white). However someone (not me) could argue that this will expose implementation details which is usually thing to avoid while writing unit test.

Objective-C class not recognized

I'm new to Objective-C and I'm trying to use the UIImage+Resize class to resize a picture in iOS. See UIIimage+Resize.m code.
The resizeImage class is not recognized by XCode in the following code.
Error message: "Class method resizedImage:interpolationQuality not
found..."
#import "UIImage+Resize.h"
- (void)useImage:(UIImage*)theImage {
...
...
...
CGSize newSize = CGSizeMake (newWidth, newHeight);
CGInterpolationQuality InterpQual = kCGInterpolationHigh;
UIImage* newImg = [UIImage resizedImage:newSize interpolationQuality:InterpQual];
...
...
...
}
You are calling that method as if it was a class method ([UIImage ...]) however it's an instance method (note the leading -). So you need an instance of UIImage to call it on instead.
create an instance of UIImage before calling resize methode

What is the recommended method of styling an iOS app?

What is the recommended method of styling an iOS app? For example, if there are multiple labels or text views how can updating font style/color at one place update the style/color at all other places?
I know sub classing could be one way... is there any other way?
You could import a standard header file into all your controllers with several constants set for styling... example:
Styles.h
#define kFontSize 14
#define kFontFamily #"Helevetica"
Controller
#import "Styles.h" // at the top
myLabel.font = [UIFont fontWithName:kFontFamily size:kFontSize];
I personally think Interface Builder is the best way to style, however this answers your question directly.
Update: I would recommend starting by understanding UIAppearance APIs, and seeing how well they suit your needs. UIAppearance is a convenient way to provide custom default stylization of specific controls' attributes at multiple levels (e.g. globally or contextually).
My original answer, which predated UIAppearance's availability:
since we're working with an object based language...
for the implementation, it depends on how you want it to behave/execute. when the implementation becomes nontrivial, i will often create a protocol. you could use class methods or instance methods and significantly optimize these types for your usage because you create fewer intermediate colors, fonts, images, etc.
a basic interface could take the form:
#protocol MONLabelThemeProtocol
- (UIFont *)labelFont;
- (UIColor *)labelTextColor;
- (UITextAlignment)labelTextAlignment;
// ...
#end
#protocol MONTableViewCellThemeProtocol
- (UIFont *)tableViewCellFont;
- (UIColor *)tableViewCellTextColor;
- (UIImage *)tableViewCellImage;
- (NSInteger)tableViewCellIndentationLevel;
- (CGFloat)tableViewCellIndentationWidth;
// ...
#end
then a simple amalgamate theme could be declared like this:
#interface MONAmalgamateThemeBase : NSObject
< MONLabelThemeProtocol, MONTableViewCellThemeProtocol >
{
#protected
/* labels */
UIFont * labelFont;
UIColor * labelTextColor;
UITextAlignment labelTextAlignment;
// ...
/* table view cells */
UIFont * tableViewCellFont;
UIColor * tableViewCellTextColor;
UIImage * tableViewCellImage;
NSInteger tableViewCellIndentationLevel;
CGWidth tableViewCellIndentationWidth;
// ...
}
#end
in this example, the amalgamate defines the getters and dealloc and expects the subclasses to initialize the instance variables. you could also support lazy initialization if initialization times are high (e.g. uses many images).
then a specialization could take the form:
#interface MONDarkTheme : MONAmalgamateThemeBase
#end
#implementation MONDarkTheme
- (id)init
{
self = [super init];
if (nil != self) {
labelFont = [[UIFont boldSystemFontOfSize:15] retain];
labelTextColor = [[UIColor redColor] retain];
// and so on...
}
return self;
}
// ...
#end
/* declare another theme and set it up appropriately */
#interface MONLightTheme : MONAmalgamateThemeBase
#end
then just reuse the theme instances (e.g. MONDarkTheme) throughout the app to stylize the views. if you have a lot of themes or they are not trivial to construct, then you may want to create a collection for themes (theme manager). the amalgamate could also take a parameter, such as init with theme if your needs are simple. you can even configure objects to register for changes to themes, if you need support for dynamic changes.
finally, you can create a simple theme applier to make life easier - like so:
#interface UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme;
#end
#implementation UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme
{
assert(theme);
if (nil == theme) return;
self.font = [theme labelFont];
self.textColor = [theme labelTextColor];
self.textAlignment = [theme labelTextAlignment];
}
#end
Frankly, the best way to go about this is to use Interface Builder. While it might seem nice to change a single constant somewhere in the code and have the entire app change styles, it never quite works out that way. Here are my reasonings:
1) Developers don't write interface code as well as interface builder does.
Interface builder is a tool that has been refined, tested, and intreated over years. It offers fonts, text alignment, shadow, etc. It is backwards compatible for as far back as you'd ever want. It provides a very simple way for any number of developers and designers to jump in and work on something very straightforward.
2) There are always edge cases that you'll have to account for. Sure, a simple constant will do what you want most the time, but you'll eventually have to hack something in here and sneak something in there. The "simple" interface code you wrote to start off will grow and grow and grow. Other developers will have to maintain that code. You will have to maintain that code. You will have to file and fix bugs, tweak this, except that, etc. It will inevitably become a steaming pile of mess.
3) The more code you write, the more bugs you write. Interface builder is for building the 'look' of most iOS apps. Use it. Don't get too clever.
NOTE:
I understand that Interface builder cannot do everything for all apps. There are cases that coding an interface is the only solution. This answer is simply a general "best practice" I use in the bulk of my apps.
Similar to Alex's idea, you could create a static class called ThemeManager:
typedef enum
{
defaultStyle,
redStyle,
} ThemeStyles;
#interface Level : NSObject
{
ThemeStyles currentTheme;
}
All classes which can be themed will import ThemeManager. Then, you can create methods like:
+ (UIColor*) fontColor;
Which other classes would call when they want a color for their font. Then, if you want to change themes, you could implement fontColor as:
+ (UIColor*) fontColor
{
switch (currentTheme)
{
case defaultStyle:
return [UIColor blackColor];
case redStyle:
return [UIColor redColor];
}
}
When you want to change the theme, you could have ThemeManager implement a method like:
+ (void) changeTheme:(ThemeStyles)newTheme
{
currentTheme = newTheme;
}
You can use a third-party abstraction of UIAppearance:
NUI: https://github.com/tombenner/nui
Pixate: http://www.pixate.com
Using a Storyboard has a lot of benefits, but many style options aren't available, not the least of which is custom fonts. If you want a deeply-customized UI, you will need some style code to make it happen.
I use plists. Just as I localize strings, I use the same procedure to change themes. I coded a singleton that loads a current theme plist and a fallback plist. Then I replace the names of resources with keys and macro functions that pull the real resource name from the singleton.
Cons: you have to set the resource for each element, not just set it in the NIB.
Pros: once you are done, most of the next theme involves photoshop and textmate, not IB or code.
You may need to look at this library. It supports multiple themes/skins on the fly. Supports images and colors currently. Font support will be added in future.
https://github.com/charithnidarsha/MultiThemeManager

External Constants for UIColor, UIFont, etc

I have a constants.m file that is a centralized collection of many program constants. To set a color, I do this:
#implementation UIColor (UIColor_Constants)
+(UIColor *) defaultResultTableBackgroundColor{
//return [[UIColor colorWithRed:0.6f green:0.004f blue:0.0f alpha:1.0f] retain];
return [[UIColor colorWithRed:0.1f green:0.004f blue:0.3f alpha:0.3f] retain];
}
+(UIColor *) defaultResultHeaderBackgroundColor{
return [[UIColor clearColor] retain];
}
#end
and in the constants.h I have
#interface UIColor (UIColor_Constants)
+(UIColor *) defaultResultTableBackgroundColor;
+(UIColor *) defaultResultHeaderBackgroundColor;
#end
and then just use [UIColor defaultResultTableBackgroundColor] where I want to refer to this constant.
I would like to have some other UIColor and UIFont constants, and, while this works, it seems to be more complicated than it needs to be. Is there an easier way to do this?
I use a constants file for the same purpose. Rather than setting up a whole interface and implementation file, I create the constants file as just the header (.h) file. Then, I define the colors I want to use, such as:
#define globalColor [UIColor colorWithRed:0.1f green:0.004f blue:0.3f alpha:0.3f]
Then, any time you use globalColor it's just like typing in the defined code.
I actually like this way too. One question: why do you retain the uicolor?
This is very dangerous. It's very likely to make a mistake and to create a memory leak.
Here's a great read that explains constants in Objective C:
What is the best way to create constants in Objective-C
Short answer: You're handling this the best way possible.
Macros are not recommended. As some have mentioned, you could #define a macro to handle your colors. That's essentially telling the preprocessor to run find-and-replace on your code. There's a number of downsides to this approach, including scope and type. Apple explicitly recommends against these types of 'constants": https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html
It's also possible to create a constant:
(in your header, file scope)
extern UIColor * const COLOR_LIGHT_BLUE;
(in your implementation, file scope)
UIColor* const COLOR_LIGHT_BLUE = [[UIColor alloc] initWithRed:21.0f/255 green:180.0f/255 blue:1 alpha:1];
You could, of course, #import this header in your prefix header to save even more typing. Ultimately, though, it's not much of an improvement over what you're already doing.
You create a constant header file which contains all your colors and/or fonts like that:
// Define a convenient macro for example
#define HEXCOLOR(c) [UIColor colorWithRed:((c>>16)&0xFF)/255.0 \
green:((c>>8)&0xFF)/255.0 \
blue:c&0xFF/255.0 \
alpha:0xFF/255.0]
// Then define your constants
#define DefaultResultTableBackgroundColor HEXCOLOR(0x151515)
// etc.
Answer is very simple. It can be used for NSArray and NSDictionary etc.
//Font
static UIFont *titleFont() {
static UIFont *font = nil;
if (!font) {
font = [UIFont systemFontOfSize:25 weight:UIFontWeightHeavy];
}
return font;
}
//Color
static UIColor *prettyPurpleColor() {
static UIColor *color = nil;
if (!color) {
color = [[UIColor purpleColor] colorWithAlphaComponent:0.35];
}
return color;
}