I'm having trouble with a school problem in Objective C. I need to build 3 methods. The first method tells you if someone is in a line. If nobody is in the line it tells you nobody is in the line otherwise it tells you who is in the line and it lists the names on a new line.
The second method adds names to the line.
The third method removes a name from the line and tells you who was removed.
First method:
-(NSString*)stringWithDeliLine:(NSArray*) deliLine{
NSString *empty = #"The line is currently empty.";
//Some kind of formatted string
if(deliLine == nil || [deliLine count] == 0)
{
empty;
}
else
{
//formatted string
}
//not sure how to return either empty or formatted string
}
Second Method:
-(void)addName:toDeliLine:(NSString*)name:(NSMutableArray*)deliLine{
[deliLine addObject:name];
}
The third method I was going to use removeObject but the instructions said not to use it so I have no idea where to start.I have the signature I think.
-(NSString*)serveNextCustomerInDeliLine:(NSMutableArray*)deliLine{
return nil;
}
For the first method I'm not sure why my literal string won't work in the if statement. I thought I was saying look at the array if nothing is in the array then it's the first object and show the string literal. else show some kinda of formatted string. I've tried all kinds of strings but none seem to be working so that's why I have the comment formatted string. If someone could give me a hint that would be great. I don't need the answer just a clue on what to think about. This is long post sorry.
A possible implementation can be the following. Please note that I have not testes edge cases and I wrote the code without Xcode support
#import <Foundation/Foundation.h>
#interface Line : NSObject
- (NSString*)printLine;
- (void)addCustomer:(NSString*)customer;
- (NSString*)removeCustomer:(NSString*)customer;
#end
#import "Line.h"
#interface Line ()
#property (nonatomic, strong, readwrite) NSMutableArray<NSString*> *customers;
#end
#implementation Line
- (instancetype)init {
self = [super init];
if (self) {
_customers = [NSMutableArray array];
}
return self;
}
- (NSString*)printLine {
NSUInteger count = self.customers.count;
if(count == 0) {
return #"Empty";
}
NSMutableString *descr = [NSMutableString string];
for (NSString *customer in self.customers) {
[descr appendString:[NSString stringWithFormat:#"%# ", customer]];
}
return [descr copy];
}
- (void)addCustomer:(NSString*)customer {
[self.customers addObject:customer];
}
- (NSString*)removeCustomer:(NSString*)customer {
NSUInteger index = [self.customers indexOfObject:customer];
if(index == NSNotFound) {
return [NSString stringWithFormat:#"%# not removed", customer];
}
NSString *removedCustomer = [self.customers objectAtIndex:index];
[self.customers removeObjectAtIndex:index];
return removedCustomer;
}
#end
Usage:
Line *line = [[Line alloc] init];
[line addCustomer:#"customer"];
NSLog(#"%#", [line printLine]);
NSLog(#"%#", [line removeCustomer:#"customer"]);
NSLog(#"%#", [line printLine]);
Edit:
I've updated my answer, passing the array as a parameter is not necessary, just initialize deliLine as a mutable array property.
For you first method, you could do the following,
- (NSString *)deliLineContents {
NSString *empty = #"The line is currently empty.";
NSMutableString *namesInQueue = [[NSMutableString alloc] init];
if(self.deliLine == nil || [self.deliLine count] == 0) {
return empty;
} else {
// Loop through your array and return a string of all the names
for (NSString *string in self.deliLine ) {
[namesInQueue appendString:string];
}
}
return [NSString stringWithString:namesInQueue];
For your second method, you're already pretty much there, maybe look up how to construct method signatures.
- (void)addNameToDeliLine:(NSString*)name {
[self.deliLine addObject:name];
}
For your third method, not sure if this meets your requirement, if not let me know.
- (NSString *)customerRemovedFromLine {
// I've making an assumption that you want to remove the first customer
NSString *servedCustomer = [self.deliLine objectAtIndex:0];
[self.deliLine removeObjectAtIndex:0];
return servedCustomer;
}
You probably don't need to pass deliLine around, just create it as a property and access it with self.deliLine. Anyway hope this helps, good luck.
Related
I'm working on a react-native project that requires some native modules. One of them is a Bluetooth module that allows me to access some CSRGaia methods. Ultimately, I want to be able to read the eq values on the PS-key so that I can set my equalizer to the corresponding values. I know almost nothing about Objective-C
Currently there is a method that looks like this:
RCT_EXPORT_METHOD(setEQValues:(NSArray *)values callback:(RCTResponseSenderBlock)callback)
{
CSRPeripheral *connectedPeripheral = [CSRConnectionManager sharedInstance].connectedPeripheral;
if( connectedPeripheral == nil )
{
callback(#[DISCONNECTED]);
return;
}
[[CSRGaia sharedInstance] setEQValues:values];
}
This works with no issues. However, when I tried to write my own
RCT_EXPORT_METHOD(getUserEQ: (NSArray *)values callback:(RCTResponseSenderBlock)callback)
{
CSRPeripheral *connectedPeripheral = [CSRConnectionManager sharedInstance].connectedPeripheral;
if( connectedPeripheral == nil)
{
callback(#[DISCONNECTED]);
return;
}
[[CSRGaia sharedInstance] getUserEQ: values];
}
I get the following error:
No visible #interface for 'CSRGaia' declares the selector 'getUserEQ:'
I double checked the CSRGaia.m file to verify that both methods exist.
- (void)setEQValues:(NSArray *)values {
NSMutableData *payload = [[NSMutableData alloc] init];
for( NSNumber *value in values ) {
uint8_t hex = [value unsignedCharValue];
[payload appendBytes:&hex length:1];
}
[self sendCommand:GaiaCommand_SET_HEP_EQ_PSKEY
vendor:CSR_GAIA_VENDOR_ID
data:payload];
}
- (void)getUserEQ {
[self sendCommand:GaiaCommand_GetUserEQControl
vendor:CSR_GAIA_VENDOR_ID
data:nil];
}
you are calling this method:
'getUserEQ:'
notice the 2 dots colon
it's different from method
'getUser'
with no colon
and in your .m file there is only
- (void)getUserEQ {}
i guess you wanted to use the setter method, instead
- (void)setEQValues:(NSArray *)values{}
like this:
[[CSRGaia sharedInstance] setEQValues: values];
add anyway both
- (void)getUserEQ;
- (void)setEQValues:(NSArray *)values;
in CSRGaia.h file
between
#interface OSRGaia
and
#end
I wanted to get only array string value app. As example(SLGoogleAuth ,HalfTunes,TheBackgrounder,Calculiator) . But don't know how to do?
It's a code.
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSLog(#"apps: %#", [workspace performSelector:selectorALL]);
}
It's output:
Thanks in advance
You do not want to parse that. NSLog prints out a description of an object. You want to access that value directly.
[LSApplicationWorkspace allApplications];
returns NSArray of LSApplicationProxy. LSApplicationProxy class has a ivar _bundleURL that contains information that you need. You need runtime functions to access it. Working example below:
// #import <objc/runtime.h>
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSArray* appProxies = [workspace performSelector:selectorALL];
Ivar bundleUrlIvar = class_getInstanceVariable([appProxies.firstObject class], "_bundleURL");
NSMutableString* result = [NSMutableString string];
for (id appProxy in appProxies)
{
NSURL* url = object_getIvar(appProxy, bundleUrlIvar);
// at this point you have the information and you can do whatever you want with it
// I will make it a list as you asked
if (url)
{
[result appendFormat:#",%#", [url lastPathComponent]];
}
}
if (result.length > 0)
{
// remove comma from beginning of the list
[result deleteCharactersInRange:NSMakeRange(0, 1)];
}
NSLog(#"apps: %#", result);
Note that this will be rejected by AppStore as you are using private apis. So use at your own discretion.
I'm fairly new to Objective-C; but have been coding for years and this one really stumps me.
I'm trying to build an iPhone app and wanted to create a "settings" screen which will use a Table format. (Xcode 5.1.1).
I want to future proof the main Settings screen and make it easy for the application coding by hiding the "hard work" in subroutines/methods.
I may be getting too clever but I've created a class for each 'setting' that contains screen prompts, default values etc and using an Enum to cross-reference it (so the compiler will highlight typos etc)
The problem I'm encountering is that when I add entries to my NSMutableDictionary and use lldb to print the values; every entry seems to have the same "key" and values. I've tried converting the eNum to an NSNumber and also as an NSString -- no difference in the result - so I'm obviously doing something else daft but just can't see it
The following code is from various .m & .h files, I've omitted boring stuff that you always "have to have" to keep it short
// basic x-ref I want to use in my code
typedef NS_OPTIONS(NSInteger, ConfigurationType) {
unDefined = -1,
Server = 0,
Id = 1,
Phone = 2
};
// definition for a "single" Settings value
#interface SettingDefinition : NSObject
#end
#implementation SettingDefinition
ConfigurationType _cfgType;
NSString *_cfgName;
NSString *_screenTitle;
NSString *_value;
- (NSString *)description
{
NSString *className = NSStringFromClass([self class]);
return [NSString stringWithFormat:#"<%#: x%p Type=%d dbKey=%# '%#' -> %#>", className, self, _cfgType, _cfgName, _screenTitle, _value];
}
- (id)initType:(ConfigurationType)cfgOption
withDbKey: (NSString*)dbKey
asOptionTitle:(NSString*)cfgTitle
withValue:(NSString*)itmValue
{
self = [super init];
if (self) {
_screenTitle = cfgTitle;
_cfgName = dbKey;
_cfgType = cfgOption;
_value = itmValue;
}
return self;
}
#end
#interface Configuration : NSObject
#end
#implementation Configuration {
NSMutableDictionary *Settings; // List of Setting structures
};
- (id)init {
self = [super init];
if (self) {
Settings = [[NSMutableDictionary alloc]init];
[self add:Server withDbKey:#"Server" asOptionTitle:#"Server"];
[self add:Id withDbKey:#"Id" asOptionTitle:#"Your ID"];
[self add:Phone withDbKey:#"Phone" asOptionTitle:#"Phone No."];
}
return self;
}
- (void) add:(ConfigurationType)cfgOption
withDbKey:(NSString*)dbKey
asOptionTitle:(NSString*)cfgTitle
{
NSString * itmValue = [self configurationValue: cfgOption cfgName:dbKey];
SettingDefinition *x = [[SettingDefinition alloc]
initType: cfgOption
withDbKey: dbKey
asOptionTitle: cfgTitle
withValue: itmValue];
[Settings setObject:x forKey:[self asKey:cfgOption]];
}
- (NSString *) asKey:(ConfigurationType) settingType {
NSString *rc = [NSString stringWithFormat:#"%d", settingType];
return rc;
}
- (NSString *) configurationValue:(ConfigurationType) settingType {
// returns a suitable value from my system setup
// which is initially a null value until the user sets everything up
}
the debug window shows the following when I break after the final call to [self add: ...]
(lldb) po Settings
{
0 = "<SettingDefinition: x0x8e7c280 Type=2 dbKey=Phone 'Phone No.' -> (null)>";
1 = "<SettingDefinition: x0x8c703a0 Type=2 dbKey=Phone 'Phone No.' -> (null)>";
2 = "<SettingDefinition: x0x8e7c310 Type=2 dbKey=Phone 'Phone No.' -> (null)>";
}
The (null) is obviously due to no data in 'value' yet; but why do they all show as 'Phone'; if I break after the second call to [self add:..] they all show as 'Id'
UPDATE:
DOH! obviously they're globals (I've been using another IDE where everything is local until exposed) .. If I enclose them in braces in the implementation as the documentation states then the exhibited problem vanishes. I have properties to access the variables but as the setter does more than just set the memory, I thought I'd need my "own" variables to hold the data.. said it was something daft .. thank you!
In my app I read contacts from address book, but for some of them, the name fields is empty. I want to put them at the end of my list by using a special string. What sort of special string should I use to make sure when the array is getting sorted ascending, person with missing name is placed at the end of the array?
for example my name array is
array = #[#"Andy", #"Brad", #"Zoro", #"[missing name]"];
[array sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
I have tried using <UNKNOWN NAME> or [UNKNOWN NAME] or <UNKONWN NAME> but they all turned out to be in earlier position than Andy
Thank you in advance.
Conventional
Don't use a special string for missing names; don't do unnatural things just because you are missing data. Write your own message that uses localizedCaseInsensitiveCompare:, and put it in your own category on NSString.
// NSStringEmptyLast.h
#interface NSString (EmptyLast)
- (NSComparisonResult)localizedCaseInsensitiveCompareEmptyLast:(NSString *)aString
#end
// NSStringEmptyLast.m
#import NSStringEmptyLast.h
#implementation NSString (EmptyLast)
- (NSComparisonResult)localizedCaseInsensitiveCompareEmptyLast:(NSString *)aString {
if ([self length] == 0 && [aString length] == 0) {
return NSOrderedSame;
} else if ([self length] == 0 && [aString length] != 0) {
return NSOrderedDescending;
} else if ([self length] != 0 && [aString length] == 0) {
return NSOrderedAscending;
} else {
return [self localizedCaseInsensitiveCompare:aString];
}
}
#end
Then, use:
[array sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompareEmptyLast:)];
Don't be afraid to add messages for existing classes.
Blocks
Or, if you don't want to write a category, use
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr
where cmptr is a NSComparator block, which should have the equivalent of the message given above.
Try using curly brackets: {…}, pipe: |, or tilde: ~.
Here is what I ended up with. Since I want to avoid array sorting after query from the database. I setup a fake string to people that doesn't have name. This might not be the most elegant answer but it will make people with this name appear last if I query from core data using name in ascending order.
// Person+UnknownName.h
#interface Person (UnknownName)
+ (NSString)unknownName
#end
// Person+UnknownName.m
#import "Person+UnknownName.h"
#implementation Person (UnknownName)
+ (NSString)unknownName {
unichar lastcharacter = 0xffffffff;
NSString * UNKNOWN_NAME = [NSString stringWithCharacters:&lastcharacter length:1];
}
#end
I was writing a small Category on NSString, and I wanted to know if this method is accurately handles all potential use cases:
Update: to clarify -- I wanted to make sure I'm not missing some oddball case involving character encodings, etc..
#implementation NSString (Helpers)
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
if (!aString)
return YES;
return [aString isEqualToString:#""];
}
#end
Sample usage:
-(void) sampleUsage {
NSString *emptyString = #"";
NSString *nilString = nil;
NSAssert([NSString stringIsNilOrEmpty:nilString] == YES, #"String is nil/empty");
NSAssert([NSString stringIsNilOrEmpty:emptyString] == YES, #"String is nil/empty");
}
#end
I only use the next conditional and do not even need a category:
if (!aString.length)
{
...
}
Using Objective-C theory, a message to NIL will return nil or zero, so basically you do not have to test for nil.
You can simplify the code by removing conditional:
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
return !(aString && aString.length);
}
#dasblinkenlight's answer is fine, but a much more readable conditional check I would use is:
NSString *string = ...; // define the string
if ([string length] == 0) {
// Do stuff with the string
} else {
// The string is empty or nil here
}
Very concise and does not require a separate convenience function definition. It's easy enough to remember.
EDIT: #Michael G. Emmons posted this as the last comment to that answer... credit to him but I'm listing this as an answer in its own right.
Some examples of this sort of "is not empty or blank" tests as a category on NSString.
// Please note that in general I advocate using a prefix on category methods
// to avoid category collisions. I've not done this here for clarity.
// The #interface is also excluded from this example for brevity.
#implementation NSString (MyAdditions)
- (BOOL)isNotEmpty
{
return [self length] != 0;
}
- (BOOL)isNotBlank
{
if ([self isNotEmpty])
{
NSCharacterSet *nonWhitespaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet];
NSRange range = [self rangeOfCharactersFromSet:nonWhitespaceSet];
return range.location != NSNotFound;
}
return NO;
}
#end
Simply Check your string length
> if (!yourString.length){
> //your code } a
message to NIL will return nil or 0, so no need to test for nil :).
Happy coding ...
Make sure to check for spaces, trim white spaces before calculating length.
+(BOOL)stringIsNilOrEmpty:(NSString*)aString {
return !aString || [[aString stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]] length] == 0;
}